打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux内核--网络协议栈深入分析(四)--套接字内核初始化和创建过程3

3、套接字的创建

套接字分BSD socket的传输层的socket(struct sock结构,与具体的传输层协议有关)。

3.1、BSD socket的创建

应用程序使用函数socket会产生系统调用,调用sys_socket函数来创建BSD socket:

  1. SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)  
  2. {  
  3.     int retval;  
  4.     struct socket *sock;  
  5.     int flags;  
  6.   
  7.     /* Check the SOCK_* constants for consistency.  */  
  8.     BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);  
  9.     BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);  
  10.     BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);  
  11.     BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);  
  12.   
  13.     flags = type & ~SOCK_TYPE_MASK;  
  14.     if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))  
  15.         return -EINVAL;  
  16.     type &= SOCK_TYPE_MASK;  
  17.   
  18.     if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))  
  19.         flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;  
  20.   
  21.     retval = sock_create(family, type, protocol, &sock);//调用sock_create创建套接字,参数分别是协议族号、套接字类型,使用的传输层协议、执行要创建的套接字的指针的地址。   
  22.     if (retval < 0)  
  23.         goto out;  
  24.   
  25.     retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));  
  26.     if (retval < 0)  
  27.         goto out_release;  
  28.   
  29. out:  
  30.     /* It may be already another descriptor 8) Not kernel problem. */  
  31.     return retval;  
  32.   
  33. out_release:  
  34.     sock_release(sock);  
  35.     return retval;  
  36. }  
函数sock_create会调用__sock_create函数进行套接字的创建:
  1. int __sock_create(struct net *net, int family, int type, int protocol,  
  2.              struct socket **res, int kern)  
  3. {  
  4.     int err;  
  5.     struct socket *sock;  
  6.     const struct net_proto_family *pf;  
  7.   
  8.     /* 
  9.      *      合法性检查 
  10.      */  
  11.     if (family < 0 || family >= NPROTO)  
  12.         return -EAFNOSUPPORT;  
  13.     if (type < 0 || type >= SOCK_MAX)  
  14.         return -EINVAL;  
  15.   
  16.     /* Compatibility. 
  17.  
  18.        This uglymoron is moved from INET layer to here to avoid 
  19.        deadlock in module load. 
  20.      */  
  21.     if (family == PF_INET && type == SOCK_PACKET) {  
  22.         static int warned;  
  23.         if (!warned) {  
  24.             warned = 1;  
  25.             printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",  
  26.                    current->comm);  
  27.         }  
  28.         family = PF_PACKET;  
  29.     }  
  30.   
  31.     err = security_socket_create(family, type, protocol, kern);  
  32.     if (err)  
  33.         return err;  
  34.   
  35.     /* 
  36.      *  Allocate the socket and allow the family to set things up. if 
  37.      *  the protocol is 0, the family is instructed to select an appropriate 
  38.      *  default. 
  39.      */  
  40.     sock = sock_alloc();//分配inode结构并获得对应的socket结构   
  41.     if (!sock) {  
  42.         if (net_ratelimit())  
  43.             printk(KERN_WARNING "socket: no more sockets\n");  
  44.         return -ENFILE; /* Not exactly a match, but its the 
  45.                    closest posix thing */  
  46.     }  
  47.   
  48.     sock->type = type;  
  49.   
  50.     rcu_read_lock();  
  51.     pf = rcu_dereference(net_families[family]);  
  52.     err = -EAFNOSUPPORT;  
  53.     if (!pf)  
  54.         goto out_release;  
  55.   
  56.     /* 
  57.      * We will call the ->create function, that possibly is in a loadable 
  58.      * module, so we have to bump that loadable module refcnt first. 
  59.      */  
  60.     if (!try_module_get(pf->owner))//模块检测   
  61.         goto out_release;  
  62.   
  63.     /* Now protected by module ref count */  
  64.     rcu_read_unlock();  
  65.   
  66.     //这里调用inet_create函数对INET协议族进行创建   
  67.     err = pf->create(net, sock, protocol, kern);  
  68.     if (err < 0)  
  69.         goto out_module_put;  
  70.   
  71.     /* 
  72.      * Now to bump the refcnt of the [loadable] module that owns this 
  73.      * socket at sock_release time we decrement its refcnt. 
  74.      */  
  75.     if (!try_module_get(sock->ops->owner))  
  76.         goto out_module_busy;  
  77.   
  78.     /* 
  79.      * Now that we're done with the ->create function, the [loadable] 
  80.      * module can have its refcnt decremented 
  81.      */  
  82.     module_put(pf->owner);  
  83.     err = security_socket_post_create(sock, family, type, protocol, kern);  
  84.     if (err)  
  85.         goto out_sock_release;  
  86.     *res = sock;  
  87.   
  88.     return 0;  
  89.   
  90. out_module_busy:  
  91.     err = -EAFNOSUPPORT;  
  92. out_module_put:  
  93.     sock->ops = NULL;  
  94.     module_put(pf->owner);  
  95. out_sock_release:  
  96.     sock_release(sock);  
  97.     return err;  
  98.   
  99. out_release:  
  100.     rcu_read_unlock();  
  101.     goto out_sock_release;  
  102. }  

其中的参数protocol的取值如下:

  1. /* Standard well-defined IP protocols.  */  
  2. enum {  
  3.   IPPROTO_IP = 0,       /* Dummy protocol for TCP       */  
  4.   IPPROTO_ICMP = 1,     /* Internet Control Message Protocol    */  
  5.   IPPROTO_IGMP = 2,     /* Internet Group Management Protocol   */  
  6.   IPPROTO_IPIP = 4,     /* IPIP tunnels (older KA9Q tunnels use 94) */  
  7.   IPPROTO_TCP = 6,      /* Transmission Control Protocol    */  
  8.   IPPROTO_EGP = 8,      /* Exterior Gateway Protocol        */  
  9.   IPPROTO_PUP = 12,     /* PUP protocol             */  
  10.   IPPROTO_UDP = 17,     /* User Datagram Protocol       */  
  11.   IPPROTO_IDP = 22,     /* XNS IDP protocol         */  
  12.   IPPROTO_DCCP = 33,        /* Datagram Congestion Control Protocol */  
  13.   IPPROTO_RSVP = 46,        /* RSVP protocol            */  
  14.   IPPROTO_GRE = 47,     /* Cisco GRE tunnels (rfc 1701,1702)    */  
  15.   
  16.   IPPROTO_IPV6   = 41,      /* IPv6-in-IPv4 tunnelling      */  
  17.   
  18.   IPPROTO_ESP = 50,            /* Encapsulation Security Payload protocol */  
  19.   IPPROTO_AH = 51,             /* Authentication Header protocol       */  
  20.   IPPROTO_BEETPH = 94,         /* IP option pseudo header for BEET */  
  21.   IPPROTO_PIM    = 103,     /* Protocol Independent Multicast   */  
  22.   
  23.   IPPROTO_COMP   = 108,                /* Compression Header protocol */  
  24.   IPPROTO_SCTP   = 132,     /* Stream Control Transport Protocol    */  
  25.   IPPROTO_UDPLITE = 136,    /* UDP-Lite (RFC 3828)          */  
  26.   
  27.   IPPROTO_RAW    = 255,     /* Raw IP packets           */  
  28.   IPPROTO_MAX  
  29. };  
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
LINUX下PING与TCP_IP协议栈学习笔记(1) - TCP/IP - Linux
Android socket创建、绑定流程分析(一)
addrinfo+getaddrinfo
传输模型和套接字
10、socket()函数用法详解:创建套接字
利用原始套接字抓取数据
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服