zoukankan      html  css  js  c++  java
  • Linux内核网络协议栈深入分析(三)BSD socket和传输层sock

    本文分析基于Linux Kernel 3.2.1

    原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7979838

    更多请查看专栏http://blog.csdn.net/column/details/linux-kernel-net.html

    作者:闫明


    Linux内核中协议族有INET协议族,UNIX协议族等,我们还是以INET协议族为例。

    下面是内核中的协议族声明:

    1. /* Supported address families. */  
    2. #define AF_UNSPEC   0  
    3. #define AF_UNIX     1   /* Unix domain sockets      */  
    4. #define AF_LOCAL    1   /* POSIX name for AF_UNIX   */  
    5. #define AF_INET     2   /* Internet IP Protocol     */  
    6. #define AF_AX25     3   /* Amateur Radio AX.25      */  
    7. #define AF_IPX      4   /* Novell IPX           */  
    8. #define AF_APPLETALK    5   /* AppleTalk DDP        */  
    9. #define AF_NETROM   6   /* Amateur Radio NET/ROM    */  
    10. #define AF_BRIDGE   7   /* Multiprotocol bridge     */  
    11. #define AF_ATMPVC   8   /* ATM PVCs         */  
    12. #define AF_X25      9   /* Reserved for X.25 project    */  
    13. #define AF_INET6    10  /* IP version 6         */  
    14. #define AF_ROSE     11  /* Amateur Radio X.25 PLP   */  
    15. #define AF_DECnet   12  /* Reserved for DECnet project  */  
    16. #define AF_NETBEUI  13  /* Reserved for 802.2LLC project*/  
    17. #define AF_SECURITY 14  /* Security callback pseudo AF */  
    18. #define AF_KEY      15      /* PF_KEY key management API */  
    19. #define AF_NETLINK  16  
    20. #define AF_ROUTE    AF_NETLINK /* Alias to emulate 4.4BSD */  
    21. #define AF_PACKET   17  /* Packet family        */  
    22. #define AF_ASH      18  /* Ash              */  
    23. #define AF_ECONET   19  /* Acorn Econet         */  
    24. #define AF_ATMSVC   20  /* ATM SVCs         */  
    25. #define AF_RDS      21  /* RDS sockets          */  
    26. #define AF_SNA      22  /* Linux SNA Project (nutters!) */  
    27. #define AF_IRDA     23  /* IRDA sockets         */  
    28. #define AF_PPPOX    24  /* PPPoX sockets        */  
    29. #define AF_WANPIPE  25  /* Wanpipe API Sockets */  
    30. #define AF_LLC      26  /* Linux LLC            */  
    31. #define AF_CAN      29  /* Controller Area Network      */  
    32. #define AF_TIPC     30  /* TIPC sockets         */  
    33. #define AF_BLUETOOTH    31  /* Bluetooth sockets        */  
    34. #define AF_IUCV     32  /* IUCV sockets         */  
    35. #define AF_RXRPC    33  /* RxRPC sockets        */  
    36. #define AF_ISDN     34  /* mISDN sockets        */  
    37. #define AF_PHONET   35  /* Phonet sockets       */  
    38. #define AF_IEEE802154   36  /* IEEE802154 sockets       */  
    39. #define AF_CAIF     37  /* CAIF sockets         */  
    40. #define AF_ALG      38  /* Algorithm sockets        */  
    41. #define AF_NFC      39  /* NFC sockets          */  
    42. #define AF_MAX      40  /* For now.. */  

    内核中的PF_***和AF_***其实可以混用,它的宏定义如下:

    1. /* Protocol families, same as address families. */  
    2. #define PF_UNSPEC   AF_UNSPEC  
    3. #define PF_UNIX     AF_UNIX  
    4. #define PF_LOCAL    AF_LOCAL  
    5. #define PF_INET     AF_INET  
    6. #define PF_AX25     AF_AX25  
    7. #define PF_IPX      AF_IPX  
    8. #define PF_APPLETALK    AF_APPLETALK  
    9. #define PF_NETROM   AF_NETROM  
    10. #define PF_BRIDGE   AF_BRIDGE  
    11. #define PF_ATMPVC   AF_ATMPVC  
    12. #define PF_X25      AF_X25  
    13. #define PF_INET6    AF_INET6  
    14. #define PF_ROSE     AF_ROSE  
    15. #define PF_DECnet   AF_DECnet  
    16. #define PF_NETBEUI  AF_NETBEUI  
    17. #define PF_SECURITY AF_SECURITY  
    18. #define PF_KEY      AF_KEY  
    19. #define PF_NETLINK  AF_NETLINK  
    20. #define PF_ROUTE    AF_ROUTE  
    21. #define PF_PACKET   AF_PACKET  
    22. #define PF_ASH      AF_ASH  
    23. #define PF_ECONET   AF_ECONET  
    24. #define PF_ATMSVC   AF_ATMSVC  
    25. #define PF_RDS      AF_RDS  
    26. #define PF_SNA      AF_SNA  
    27. #define PF_IRDA     AF_IRDA  
    28. #define PF_PPPOX    AF_PPPOX  
    29. #define PF_WANPIPE  AF_WANPIPE  
    30. #define PF_LLC      AF_LLC  
    31. #define PF_CAN      AF_CAN  
    32. #define PF_TIPC     AF_TIPC  
    33. #define PF_BLUETOOTH    AF_BLUETOOTH  
    34. #define PF_IUCV     AF_IUCV  
    35. #define PF_RXRPC    AF_RXRPC  
    36. #define PF_ISDN     AF_ISDN  
    37. #define PF_PHONET   AF_PHONET  
    38. #define PF_IEEE802154   AF_IEEE802154  
    39. #define PF_CAIF     AF_CAIF  
    40. #define PF_ALG      AF_ALG  
    41. #define PF_NFC      AF_NFC  
    42. #define PF_MAX      AF_MAX  

    以后的分析就是以INET协议族为例来分析的。

    下面的结构体就是在系统初始化时用来管理协议族初始化的结构体:

    1. struct net_proto_family {  
    2.     int     family;  
    3.     int     (*create)(struct net *net, struct socket *sock,  
    4.                   int protocol, int kern);  
    5.     struct module   *owner;  
    6. };  
    第一个属性就是协议族的宏定义,如PF_INET;

    第二个属性就是协议族对应的初始化函数指针;

    INET协议族对应该结构的定义如下:

    1. static const struct net_proto_family inet_family_ops = {  
    2.     .family = PF_INET,  
    3.     .create = inet_create,  
    4.     .owner  = THIS_MODULE,  
    5. };  

    下面结构体是协议族操作集结构体定义:

    1. struct proto_ops {  
    2.     int     family;  
    3.     struct module   *owner;  
    4.     int     (*release)   (struct socket *sock);  
    5.     int     (*bind)      (struct socket *sock,  
    6.                       struct sockaddr *myaddr,  
    7.                       int sockaddr_len);  
    8.     int     (*connect)   (struct socket *sock,  
    9.                       struct sockaddr *vaddr,  
    10.                       int sockaddr_len, int flags);  
    11.     int     (*socketpair)(struct socket *sock1,  
    12.                       struct socket *sock2);  
    13.     int     (*accept)    (struct socket *sock,  
    14.                       struct socket *newsock, int flags);  
    15.     int     (*getname)   (struct socket *sock,  
    16.                       struct sockaddr *addr,  
    17.                       int *sockaddr_len, int peer);  
    18.     unsigned int    (*poll)      (struct file *file, struct socket *sock,  
    19.                       struct poll_table_struct *wait);  
    20.     int     (*ioctl)     (struct socket *sock, unsigned int cmd,  
    21.                       unsigned long arg);  
    22. #ifdef CONFIG_COMPAT  
    23.     int     (*compat_ioctl) (struct socket *sock, unsigned int cmd,  
    24.                       unsigned long arg);  
    25. #endif  
    26.     int     (*listen)    (struct socket *sock, int len);  
    27.     int     (*shutdown)  (struct socket *sock, int flags);  
    28.     int     (*setsockopt)(struct socket *sock, int level,  
    29.                       int optname, char __user *optval, unsigned int optlen);  
    30.     int     (*getsockopt)(struct socket *sock, int level,  
    31.                       int optname, char __user *optval, int __user *optlen);  
    32. #ifdef CONFIG_COMPAT  
    33.     int     (*compat_setsockopt)(struct socket *sock, int level,  
    34.                       int optname, char __user *optval, unsigned int optlen);  
    35.     int     (*compat_getsockopt)(struct socket *sock, int level,  
    36.                       int optname, char __user *optval, int __user *optlen);  
    37. #endif  
    38.     int     (*sendmsg)   (struct kiocb *iocb, struct socket *sock,  
    39.                       struct msghdr *m, size_t total_len);  
    40.     int     (*recvmsg)   (struct kiocb *iocb, struct socket *sock,  
    41.                       struct msghdr *m, size_t total_len,  
    42.                       int flags);  
    43.     int     (*mmap)      (struct file *file, struct socket *sock,  
    44.                       struct vm_area_struct * vma);  
    45.     ssize_t     (*sendpage)  (struct socket *sock, struct page *page,  
    46.                       int offset, size_t size, int flags);  
    47.     ssize_t     (*splice_read)(struct socket *sock,  loff_t *ppos,  
    48.                        struct pipe_inode_info *pipe, size_t len, unsigned int flags);  
    49. };  

    INET协议族中TCP和UDP协议对应的上述操作集的定义不同:

    TCP协议z在INET层操作集inet_stream_ops

    1. const struct proto_ops inet_stream_ops = {  
    2.     .family        = PF_INET,  
    3.     .owner         = THIS_MODULE,  
    4.     .release       = inet_release,  
    5.     .bind          = inet_bind,  
    6.     .connect       = inet_stream_connect,  
    7.     .socketpair    = sock_no_socketpair,  
    8.     .accept        = inet_accept,  
    9.     .getname       = inet_getname,  
    10.     .poll          = tcp_poll,  
    11.     .ioctl         = inet_ioctl,  
    12.     .listen        = inet_listen,  
    13.     .shutdown      = inet_shutdown,  
    14.     .setsockopt    = sock_common_setsockopt,  
    15.     .getsockopt    = sock_common_getsockopt,  
    16.     .sendmsg       = inet_sendmsg,  
    17.     .recvmsg       = inet_recvmsg,  
    18.     .mmap          = sock_no_mmap,  
    19.     .sendpage      = inet_sendpage,  
    20.     .splice_read       = tcp_splice_read,  
    21. #ifdef CONFIG_COMPAT  
    22.     .compat_setsockopt = compat_sock_common_setsockopt,  
    23.     .compat_getsockopt = compat_sock_common_getsockopt,  
    24.     .compat_ioctl      = inet_compat_ioctl,  
    25. #endif  
    26. };  
    UDP协议在INET层操作集inet_dgram_ops
    1. const struct proto_ops inet_dgram_ops = {  
    2.     .family        = PF_INET,  
    3.     .owner         = THIS_MODULE,  
    4.     .release       = inet_release,  
    5.     .bind          = inet_bind,  
    6.     .connect       = inet_dgram_connect,  
    7.     .socketpair    = sock_no_socketpair,  
    8.     .accept        = sock_no_accept,  
    9.     .getname       = inet_getname,  
    10.     .poll          = udp_poll,  
    11.     .ioctl         = inet_ioctl,  
    12.     .listen        = sock_no_listen,  
    13.     .shutdown      = inet_shutdown,  
    14.     .setsockopt    = sock_common_setsockopt,  
    15.     .getsockopt    = sock_common_getsockopt,  
    16.     .sendmsg       = inet_sendmsg,  
    17.     .recvmsg       = inet_recvmsg,  
    18.     .mmap          = sock_no_mmap,  
    19.     .sendpage      = inet_sendpage,  
    20. #ifdef CONFIG_COMPAT  
    21.     .compat_setsockopt = compat_sock_common_setsockopt,  
    22.     .compat_getsockopt = compat_sock_common_getsockopt,  
    23.     .compat_ioctl      = inet_compat_ioctl,  
    24. #endif  
    25. };  

    上面两个操作集是属于INET协议族层次,可以由协议族层套接字socket来管理,下面是协议族层析的套接字结构体(BSD Socket)定义:

    1. /** 
    2.  *  struct socket - general BSD socket 
    3.  *  @state: socket state (%SS_CONNECTED, etc) 
    4.  *  @type: socket type (%SOCK_STREAM, etc) 
    5.  *  @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc) 
    6.  *  @ops: protocol specific socket operations 
    7.  *  @file: File back pointer for gc 
    8.  *  @sk: internal networking protocol agnostic socket representation 
    9.  *  @wq: wait queue for several uses 
    10.  */  
    11. struct socket {  
    12.     socket_state        state;  
    13.   
    14.     kmemcheck_bitfield_begin(type);  
    15.     short           type;  
    16.     kmemcheck_bitfield_end(type);  
    17.   
    18.     unsigned long       flags;  
    19.   
    20.     struct socket_wq __rcu  *wq;  
    21.   
    22.     struct file     *file;  
    23.     struct sock     *sk;  
    24.     const struct proto_ops  *ops;  
    25. };  

    最后一个属性就指向了上面所述的操作集。若使用TCP协议,ops就是inet_stream_ops,若是UDP协议,ops就是inet_dgram_ops。

    short type属性的取值可以是如下值:

    1. enum sock_type {  
    2.     SOCK_DGRAM  = 1,  
    3.     SOCK_STREAM = 2,  
    4.     SOCK_RAW    = 3,  
    5.     SOCK_RDM    = 4,  
    6.     SOCK_SEQPACKET  = 5,  
    7.     SOCK_DCCP   = 6,  
    8.     SOCK_PACKET = 10,  
    9. };  

    传输层的协议操作集结构体定义:

    1. struct proto {  
    2.     void            (*close)(struct sock *sk,   
    3.                     long timeout);  
    4.     int         (*connect)(struct sock *sk,  
    5.                         struct sockaddr *uaddr,   
    6.                     int addr_len);  
    7.     int         (*disconnect)(struct sock *sk, int flags);  
    8.   
    9.     struct sock *       (*accept) (struct sock *sk, int flags, int *err);  
    10.   
    11.     int         (*ioctl)(struct sock *sk, int cmd,  
    12.                      unsigned long arg);  
    13.     int         (*init)(struct sock *sk);  
    14.     void            (*destroy)(struct sock *sk);  
    15.     void            (*shutdown)(struct sock *sk, int how);  
    16.     int         (*setsockopt)(struct sock *sk, int level,   
    17.                     int optname, char __user *optval,  
    18.                     unsigned int optlen);  
    19.     int         (*getsockopt)(struct sock *sk, int level,   
    20.                     int optname, char __user *optval,   
    21.                     int __user *option);       
    22. #ifdef CONFIG_COMPAT  
    23.     int         (*compat_setsockopt)(struct sock *sk,  
    24.                     int level,  
    25.                     int optname, char __user *optval,  
    26.                     unsigned int optlen);  
    27.     int         (*compat_getsockopt)(struct sock *sk,  
    28.                     int level,  
    29.                     int optname, char __user *optval,  
    30.                     int __user *option);  
    31.     int         (*compat_ioctl)(struct sock *sk,  
    32.                     unsigned int cmd, unsigned long arg);  
    33. #endif  
    34.     int         (*sendmsg)(struct kiocb *iocb, struct sock *sk,  
    35.                        struct msghdr *msg, size_t len);  
    36.     int         (*recvmsg)(struct kiocb *iocb, struct sock *sk,  
    37.                        struct msghdr *msg,  
    38.                     size_t len, int noblock, int flags,   
    39.                     int *addr_len);  
    40.     int         (*sendpage)(struct sock *sk, struct page *page,  
    41.                     int offset, size_t size, int flags);  
    42.     int         (*bind)(struct sock *sk,   
    43.                     struct sockaddr *uaddr, int addr_len);  
    44.   
    45.     int         (*backlog_rcv) (struct sock *sk,   
    46.                         struct sk_buff *skb);  
    47.   
    48.     /* Keeping track of sk's, looking them up, and port selection methods. */  
    49.     void            (*hash)(struct sock *sk);  
    50.     void            (*unhash)(struct sock *sk);  
    51.     void            (*rehash)(struct sock *sk);  
    52.     int         (*get_port)(struct sock *sk, unsigned short snum);  
    53.     void            (*clear_sk)(struct sock *sk, int size);  
    54.   
    55.     /* Keeping track of sockets in use */  
    56. #ifdef CONFIG_PROC_FS  
    57.     unsigned int        inuse_idx;  
    58. #endif  
    59.   
    60.     /* Memory pressure */  
    61.     void            (*enter_memory_pressure)(struct sock *sk);  
    62.     atomic_long_t       *memory_allocated;  /* Current allocated memory. */  
    63.     struct percpu_counter   *sockets_allocated; /* Current number of sockets. */  
    64.     /* 
    65.      * Pressure flag: try to collapse. 
    66.      * Technical note: it is used by multiple contexts non atomically. 
    67.      * All the __sk_mem_schedule() is of this nature: accounting 
    68.      * is strict, actions are advisory and have some latency. 
    69.      */  
    70.     int         *memory_pressure;  
    71.     long            *sysctl_mem;  
    72.     int         *sysctl_wmem;  
    73.     int         *sysctl_rmem;  
    74.     int         max_header;  
    75.     bool            no_autobind;  
    76.   
    77.     struct kmem_cache   *slab;  
    78.     unsigned int        obj_size;  
    79.     int         slab_flags;  
    80.   
    81.     struct percpu_counter   *orphan_count;  
    82.   
    83.     struct request_sock_ops *rsk_prot;  
    84.     struct timewait_sock_ops *twsk_prot;  
    85.   
    86.     union {  
    87.         struct inet_hashinfo    *hashinfo;  
    88.         struct udp_table    *udp_table;  
    89.         struct raw_hashinfo *raw_hash;  
    90.     } h;  
    91.   
    92.     struct module       *owner;  
    93.   
    94.     char            name[32];  
    95.   
    96.     struct list_head    node;  
    97. #ifdef SOCK_REFCNT_DEBUG  
    98.     atomic_t        socks;  
    99. #endif  
    100. };  
    该结构体和proto_ops的区别是:该结构体和具体的传输层协议相关,其中的函数指针指向对应的协议的相应的操作函数。


    TCP协议的操作集定义如下:

    1. struct proto tcp_prot = {  
    2.     .name           = "TCP",  
    3.     .owner          = THIS_MODULE,  
    4.     .close          = tcp_close,  
    5.     .connect        = tcp_v4_connect,  
    6.     .disconnect     = tcp_disconnect,  
    7.     .accept         = inet_csk_accept,  
    8.     .ioctl          = tcp_ioctl,  
    9.     .init           = tcp_v4_init_sock,  
    10.     .destroy        = tcp_v4_destroy_sock,  
    11.     .shutdown       = tcp_shutdown,  
    12.     .setsockopt     = tcp_setsockopt,  
    13.     .getsockopt     = tcp_getsockopt,  
    14.     .recvmsg        = tcp_recvmsg,  
    15.     .sendmsg        = tcp_sendmsg,  
    16.     .sendpage       = tcp_sendpage,  
    17.     .backlog_rcv        = tcp_v4_do_rcv,  
    18.     .hash           = inet_hash,  
    19.     .unhash         = inet_unhash,  
    20.     .get_port       = inet_csk_get_port,  
    21.     .enter_memory_pressure  = tcp_enter_memory_pressure,  
    22.     .sockets_allocated  = &tcp_sockets_allocated,  
    23.     .orphan_count       = &tcp_orphan_count,  
    24.     .memory_allocated   = &tcp_memory_allocated,  
    25.     .memory_pressure    = &tcp_memory_pressure,  
    26.     .sysctl_mem     = sysctl_tcp_mem,  
    27.     .sysctl_wmem        = sysctl_tcp_wmem,  
    28.     .sysctl_rmem        = sysctl_tcp_rmem,  
    29.     .max_header     = MAX_TCP_HEADER,  
    30.     .obj_size       = sizeof(struct tcp_sock),  
    31.     .slab_flags     = SLAB_DESTROY_BY_RCU,  
    32.     .twsk_prot      = &tcp_timewait_sock_ops,  
    33.     .rsk_prot       = &tcp_request_sock_ops,  
    34.     .h.hashinfo     = &tcp_hashinfo,  
    35.     .no_autobind        = true,  
    36. #ifdef CONFIG_COMPAT  
    37.     .compat_setsockopt  = compat_tcp_setsockopt,  
    38.     .compat_getsockopt  = compat_tcp_getsockopt,  
    39. #endif  
    40. };  


    UDP协议的操作集则为:

    1. struct proto udp_prot = {  
    2.     .name          = "UDP",  
    3.     .owner         = THIS_MODULE,  
    4.     .close         = udp_lib_close,  
    5.     .connect       = ip4_datagram_connect,  
    6.     .disconnect    = udp_disconnect,  
    7.     .ioctl         = udp_ioctl,  
    8.     .destroy       = udp_destroy_sock,  
    9.     .setsockopt    = udp_setsockopt,  
    10.     .getsockopt    = udp_getsockopt,  
    11.     .sendmsg       = udp_sendmsg,  
    12.     .recvmsg       = udp_recvmsg,  
    13.     .sendpage      = udp_sendpage,  
    14.     .backlog_rcv       = __udp_queue_rcv_skb,  
    15.     .hash          = udp_lib_hash,  
    16.     .unhash        = udp_lib_unhash,  
    17.     .rehash        = udp_v4_rehash,  
    18.     .get_port      = udp_v4_get_port,  
    19.     .memory_allocated  = &udp_memory_allocated,  
    20.     .sysctl_mem    = sysctl_udp_mem,  
    21.     .sysctl_wmem       = &sysctl_udp_wmem_min,  
    22.     .sysctl_rmem       = &sysctl_udp_rmem_min,  
    23.     .obj_size      = sizeof(struct udp_sock),  
    24.     .slab_flags    = SLAB_DESTROY_BY_RCU,  
    25.     .h.udp_table       = &udp_table,  
    26. #ifdef CONFIG_COMPAT  
    27.     .compat_setsockopt = compat_udp_setsockopt,  
    28.     .compat_getsockopt = compat_udp_getsockopt,  
    29. #endif  
    30.     .clear_sk      = sk_prot_clear_portaddr_nulls,  
    31. };  


    现在介绍struct socket结构体中一个属性struct sock类型的结构体指针,这个结构体就是传输层的套接字,所有套接字通过该结构来使用网络协议的所有服务。定义如下:

    1. struct sock {  
    2.     /* 
    3.      * Now struct inet_timewait_sock also uses sock_common, so please just 
    4.      * don't add nothing before this first member (__sk_common) --acme 
    5.      */  
    6.     struct sock_common  __sk_common;  
    7. #define sk_node         __sk_common.skc_node  
    8. #define sk_nulls_node       __sk_common.skc_nulls_node  
    9. #define sk_refcnt       __sk_common.skc_refcnt  
    10. #define sk_tx_queue_mapping __sk_common.skc_tx_queue_mapping  
    11.   
    12. #define sk_dontcopy_begin   __sk_common.skc_dontcopy_begin  
    13. #define sk_dontcopy_end     __sk_common.skc_dontcopy_end  
    14. #define sk_hash         __sk_common.skc_hash  
    15. #define sk_family       __sk_common.skc_family  
    16. #define sk_state        __sk_common.skc_state  
    17. #define sk_reuse        __sk_common.skc_reuse  
    18. #define sk_bound_dev_if     __sk_common.skc_bound_dev_if  
    19. #define sk_bind_node        __sk_common.skc_bind_node  
    20. #define sk_prot         __sk_common.skc_prot  
    21. #define sk_net          __sk_common.skc_net  
    22.     socket_lock_t       sk_lock;  
    23.     struct sk_buff_head sk_receive_queue;  
    24.     /* 
    25.      * The backlog queue is special, it is always used with 
    26.      * the per-socket spinlock held and requires low latency 
    27.      * access. Therefore we special case it's implementation. 
    28.      * Note : rmem_alloc is in this structure to fill a hole 
    29.      * on 64bit arches, not because its logically part of 
    30.      * backlog. 
    31.      */  
    32.     struct {  
    33.         atomic_t    rmem_alloc;  
    34.         int     len;  
    35.         struct sk_buff  *head;  
    36.         struct sk_buff  *tail;  
    37.     } sk_backlog;  
    38. #define sk_rmem_alloc sk_backlog.rmem_alloc  
    39.     int         sk_forward_alloc;  
    40. #ifdef CONFIG_RPS  
    41.     __u32           sk_rxhash;  
    42. #endif  
    43.     atomic_t        sk_drops;  
    44.     int         sk_rcvbuf;  
    45.   
    46.     struct sk_filter __rcu  *sk_filter;  
    47.     struct socket_wq __rcu  *sk_wq;  
    48.   
    49. #ifdef CONFIG_NET_DMA  
    50.     struct sk_buff_head sk_async_wait_queue;  
    51. #endif  
    52.   
    53. #ifdef CONFIG_XFRM  
    54.     struct xfrm_policy  *sk_policy[2];  
    55. #endif  
    56.     unsigned long       sk_flags;  
    57.     struct dst_entry    *sk_dst_cache;  
    58.     spinlock_t      sk_dst_lock;  
    59.     atomic_t        sk_wmem_alloc;  
    60.     atomic_t        sk_omem_alloc;  
    61.     int         sk_sndbuf;  
    62.     struct sk_buff_head sk_write_queue;  
    63.     kmemcheck_bitfield_begin(flags);  
    64.     unsigned int        sk_shutdown  : 2,  
    65.                 sk_no_check  : 2,  
    66.                 sk_userlocks : 4,  
    67.                 sk_protocol  : 8,  
    68.                 sk_type      : 16;  
    69.     kmemcheck_bitfield_end(flags);  
    70.     int         sk_wmem_queued;  
    71.     gfp_t           sk_allocation;  
    72.     int         sk_route_caps;  
    73.     int         sk_route_nocaps;  
    74.     int         sk_gso_type;  
    75.     unsigned int        sk_gso_max_size;  
    76.     int         sk_rcvlowat;  
    77.     unsigned long           sk_lingertime;  
    78.     struct sk_buff_head sk_error_queue;  
    79.     struct proto        *sk_prot_creator;  
    80.     rwlock_t        sk_callback_lock;  
    81.     int         sk_err,  
    82.                 sk_err_soft;  
    83.     unsigned short      sk_ack_backlog;  
    84.     unsigned short      sk_max_ack_backlog;  
    85.     __u32           sk_priority;  
    86.     struct pid      *sk_peer_pid;  
    87.     const struct cred   *sk_peer_cred;  
    88.     long            sk_rcvtimeo;  
    89.     long            sk_sndtimeo;  
    90.     void            *sk_protinfo;  
    91.     struct timer_list   sk_timer;  
    92.     ktime_t         sk_stamp;  
    93.     struct socket       *sk_socket;  
    94.     void            *sk_user_data;  
    95.     struct page     *sk_sndmsg_page;  
    96.     struct sk_buff      *sk_send_head;  
    97.     __u32           sk_sndmsg_off;  
    98.     int         sk_write_pending;  
    99. #ifdef CONFIG_SECURITY  
    100.     void            *sk_security;  
    101. #endif  
    102.     __u32           sk_mark;  
    103.     u32         sk_classid;  
    104.     void            (*sk_state_change)(struct sock *sk);  
    105.     void            (*sk_data_ready)(struct sock *sk, int bytes);  
    106.     void            (*sk_write_space)(struct sock *sk);  
    107.     void            (*sk_error_report)(struct sock *sk);  
    108.     int         (*sk_backlog_rcv)(struct sock *sk,  
    109.                           struct sk_buff *skb);    
    110.     void                    (*sk_destruct)(struct sock *sk);  
    111. };  
    若sk_family是PF_INET,则sk_type可以取值:SOCK_STREAM,SOCK_DGRAM,SOCK_RAW。其中sk_prot就是指向具体协议的操作集,如TCP协议就为tcp_prot。

    若要将协议族操作集和具体协议操作集整合起来为IP协议提供接口,就需要下面的结构体定义:

    1. struct inet_protosw {  
    2.     struct list_head list;  
    3.   
    4.         /* These two fields form the lookup key.  */  
    5.     unsigned short   type;     /* This is the 2nd argument to socket(2). */  
    6.     unsigned short   protocol; /* This is the L4 protocol number.  */  
    7.   
    8.     struct proto     *prot;  
    9.     const struct proto_ops *ops;  
    10.     
    11.     char             no_check;   /* checksum on rcv/xmit/none? */  
    12.     unsigned char    flags;      /* See INET_PROTOSW_* below.  */  
    13. };  

    INET三种套接字定义的inetsw_array数组如下:

    1. static struct inet_protosw inetsw_array[] =  
    2. {  
    3.     {  
    4.         .type =       SOCK_STREAM,  
    5.         .protocol =   IPPROTO_TCP,  
    6.         .prot =       &tcp_prot,  
    7.         .ops =        &inet_stream_ops,  
    8.         .no_check =   0,  
    9.         .flags =      INET_PROTOSW_PERMANENT |  
    10.                   INET_PROTOSW_ICSK,  
    11.     },  
    12.   
    13.     {  
    14.         .type =       SOCK_DGRAM,  
    15.         .protocol =   IPPROTO_UDP,  
    16.         .prot =       &udp_prot,  
    17.         .ops =        &inet_dgram_ops,  
    18.         .no_check =   UDP_CSUM_DEFAULT,  
    19.         .flags =      INET_PROTOSW_PERMANENT,  
    20.        },  
    21.   
    22.        {  
    23.         .type =       SOCK_DGRAM,  
    24.         .protocol =   IPPROTO_ICMP,  
    25.         .prot =       &ping_prot,  
    26.         .ops =        &inet_dgram_ops,  
    27.         .no_check =   UDP_CSUM_DEFAULT,  
    28.         .flags =      INET_PROTOSW_REUSE,  
    29.        },  
    30.   
    31.        {  
    32.            .type =       SOCK_RAW,  
    33.            .protocol =   IPPROTO_IP,    /* wild card */  
    34.            .prot =       &raw_prot,  
    35.            .ops =        &inet_sockraw_ops,  
    36.            .no_check =   UDP_CSUM_DEFAULT,  
    37.            .flags =      INET_PROTOSW_REUSE,  
    38.        }  
    39. };  
    不过,在初始化的时候我们会将上面数组中的的元素按套接字类型插入inetsw链表数组中。其定义如下:

    1. static struct list_head inetsw[SOCK_MAX];  


    那内核中套接字struct socket、struct sock、struct inet_sock、struct tcp_sock、struct raw_sock、struct udp_sock、struct inet_connection_sock、struct inet_timewait_sock和struct tcp_timewait_sock的关系是怎样的呢?

    *struct socket这个是BSD层的socket,应用程序会用过系统调用首先创建该类型套接字,它和具体协议无关。

    *struct inet_sock是INET协议族使用的socket结构,可以看成位于INET层,是struct sock的一个扩展。它的第一个属性就是struct sock结构。

    *struct sock是与具体传输层协议相关的套接字,所有内核的操作都基于这个套接字。

    *struct tcp_sock是TCP协议的套接字表示,它是对struct inet_connection_sock的扩展,其第一个属性就是struct inet_connection_sock inet_conn。

    *struct raw_sock是原始类型的套接字表示,ICMP协议就使用这种套接字,其是对struct sock的扩展。

    *struct udp_sock是UDP协议套接字表示,其是对struct inet_sock套接字的扩展。

    *struct inet_connetction_sock是所有面向连接协议的套接字,是对struct inet_sock套接字扩展。

    后面两个是用于控制超时的套接字。

    就拿struct inet_sock和struct sock为例来说明,为什么内核中可以直接将sock结构体首地址强制转换成inet_sock的首地址?并且inet_sock的大小要大于sock,直接进行如下强制转换

    1. inet = inet_sk(sk);  

    1. static inline struct inet_sock *inet_sk(const struct sock *sk)  
    2. {  
    3.     return (struct inet_sock *)sk;  
    4. }  

    不会发生内存非法访问吗?!那就是在分配的时候并不只是分配的struct sock结构体大小的存储空间!

    可以细看sock结构体分配的代码:

    1. struct sock *sk_alloc(struct net *net, int family, gfp_t priority,  
    2.               struct proto *prot)  
    3. {  
    4.     struct sock *sk;  
    5.   
    6.     sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family);  
    7.     if (sk) {  
    8.         sk->sk_family = family;  
    9.         sk->sk_prot = sk->sk_prot_creator = prot;  
    10.         sock_lock_init(sk);  
    11.         sock_net_set(sk, get_net(net));  
    12.         atomic_set(&sk->sk_wmem_alloc, 1);  
    13.   
    14.         sock_update_classid(sk);  
    15.     }  
    16.   
    17.     return sk;  
    18. }  
    紧接着调用sk_prot_alloc函数分配:

    1. static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,  
    2.         int family)  
    3. {  
    4.     struct sock *sk;  
    5.     struct kmem_cache *slab;  
    6.   
    7.     slab = prot->slab;  
    8.     if (slab != NULL) {  
    9.         sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);  
    10.         ..............................  
    11.     } else  
    12.         sk = kmalloc(prot->obj_size, priority);  
    13.   
    14.     .....................  
    15.   
    16.     return sk;  
    17. ......................  
    18. }  
    上面的代码中首先判断高速缓存中是否可用,如果不可用,直接在内存分配空间,不过大小都是prot->obj_size。

    如果是TCP协议中的tcp_prot中指明该属性的大小为.obj_size = sizeof(struct tcp_sock)。

    所以,程序中给struct sock指针分配的不是该结构体的实际大小,而是大于其实际大小,以便其扩展套接字的属性占用。
    以图例说明tcp_sock是如何从sock强制转换来的:

    下篇将分析套接字的绑定、连接等一系列操作的实现。


    下篇将分析套接字的操作函数。
  • 相关阅读:
    ACM: HDU 2544 最短路-Dijkstra算法
    ACM: HDU 1874 畅通工程续-Dijkstra算法
    ACM: SGU 101 Domino- 欧拉回路-并查集
    ACM: HDU 1285 确定比赛名次
    ACM: hdu 2647 Reward -拓扑排序
    ACM: hdu 1811 Rank of Tetris
    ACM: poj 1094 Sorting It All Out
    ACM: hihicoder #1174 : 拓扑排序·一 STL- queue
    ACM: CodeForces 140A New Year Table-数学几何
    POJ 3122 Pie 二分枚举
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332904.html
Copyright © 2011-2022 走看看