关于unix网络编程的一个不错的blog,作者应该是搞协议栈,对于写应用程序的人来说,看这些东西有利于分析问题;推荐看看.
 
struct sock详解
2006年08月11日 星期五 下午 02:17   
结构体sock是套接口在网络层的表示,在代码include/net/sock.h 174行定义,下面是其内容:
    struct sock {
        struct sock_common  __sk_common;
#define sk_family       __sk_common.skc_family
#define sk_state        __sk_common.skc_state
#define sk_reuse        __sk_common.skc_reuse
#define sk_bound_dev_if     __sk_common.skc_bound_dev_if
#define sk_node         __sk_common.skc_node
#define sk_bind_node        __sk_common.skc_bind_node
#define sk_refcnt       __sk_common.skc_refcnt
        unsigned char       sk_shutdown : 2,
                            sk_no_check : 2,
                            sk_userlocks : 4;
        unsigned char       sk_protocol;
        unsigned short      sk_type;
        int         sk_rcvbuf;
        socket_lock_t       sk_lock;
        wait_queue_head_t   *sk_sleep;
        struct dst_entry    *sk_dst_cache;
        struct xfrm_policy  *sk_policy[2];
        rwlock_t        sk_dst_lock;
        atomic_t        sk_rmem_alloc;
        atomic_t        sk_wmem_alloc;
        atomic_t        sk_omem_alloc;
        struct sk_buff_head sk_receive_queue;
        struct sk_buff_head sk_write_queue;
        int         sk_wmem_queued;
        int         sk_forward_alloc;
        unsigned int        sk_allocation;
        int         sk_sndbuf;
        int         sk_route_caps;
        int         sk_hashent;
        unsigned long       sk_flags;
        unsigned long           sk_lingertime;
        struct {
            struct sk_buff *head;
            struct sk_buff *tail;
        } sk_backlog;
        struct sk_buff_head sk_error_queue;
        struct proto        *sk_prot;
        struct proto        *sk_prot_creator;
        rwlock_t        sk_callback_lock;
        int         sk_err,
                    sk_err_soft;
        unsigned short      sk_ack_backlog;
        unsigned short      sk_max_ack_backlog;
        __u32           sk_priority;
        struct ucred        sk_peercred;
        int         sk_rcvlowat;
        long            sk_rcvtimeo;
        long            sk_sndtimeo;
        struct sk_filter        *sk_filter;
        void            *sk_protinfo;
        struct timer_list   sk_timer;
        struct timeval      sk_stamp;
        struct socket       *sk_socket;
        void            *sk_user_data;
        struct page     *sk_sndmsg_page;
        struct sk_buff      *sk_send_head;
        __u32           sk_sndmsg_off;
        int         sk_write_pending;
        void            *sk_security;
        void            (*sk_state_change)(struct sock *sk);
        void            (*sk_data_ready)(struct sock *sk, int bytes);
        void            (*sk_write_space)(struct sock *sk);
        void            (*sk_error_report)(struct sock *sk);
        int             (*sk_backlog_rcv)(struct sock *sk,
                        struct sk_buff *skb);
        void            (*sk_destruct)(struct sock *sk);
    };
    __sk_common是套接口在网络层的最小表示。下面是其定义:
    struct sock_common {
        unsigned short      skc_family;         /*地址族*/
        volatile unsigned char  skc_state;      /*连接状态*/
        unsigned char       skc_reuse;          /*SO_REUSEADDR设置*/
        int         skc_bound_dev_if;
        struct hlist_node   skc_node;
        struct hlist_node   skc_bind_node;      /*哈希表相关*/
        atomic_t        skc_refcnt;             /*引用计数*/
    };
    sk_shutdown是一组标志位,SEND_SHUTDOWN and/or RCV_SHUTDOWN。
    sk_userlocks, SO_SNDBUF and SO_RCVBUF。
    sk_rcvbuf表示接收缓冲区的字节长度。
    sk_rmem_alloc表示接收队列已提交的字节数。
    sk_receive_queue表示接收的数据包的队列。
    sk_wmem_alloc表示发送队列已提交的字节数。
    sk_write_queue表示发送数据包的队列。
    sk_sndbuf表示发送缓冲区的字节长度。
    sk_flags,SO_LINGER (l_onoff),SO_BROADCAST,SO_KEEPALIVE,SO_OOBINLINE。
    sk_prot是指定的域内部的协议处理函数集,它是套接口层跟传输层之间的一个接口,提供诸如bind, accept, close等操作。
    sk_ack_backlog表示当前的侦听队列。
    sk_max_ack_backlog表示最大的侦听队列。
    sk_type表示套接字的类型,如SOCK_STREAM。
    sk_protocol表示在当前域中套接字所属的协议。
    几个函数指针均属回调函数,分别在套接口状态变化,有数据到达需要处理,有发送空间可用,有错误等时候被回调。最后一个函数sk_destruct在套接口释放时被回调。
 

inet_create如何完成对socket的创建
2006年08月11日 星期五 下午 02:18  
前面讲到在sys_socket函数中,有一步是调用net_families[family]->create完成最后的创建工作,下面就以inet域的创建来解释这最后一步的创建工作:
    1、设socket->state = SS_UNCONNECTED。
    2、从数组inetsw中匹配套接字类型和协议类型。inetsw是一个链表数组,也就是说数组的每一项是一个链表,同套接字类型的在同一个链表中。比如,用户这样创建一个TCP协议的套接字:
    socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )
    最终,内核在inetsw中匹配到的是这样一个结构体:
    static struct inet_protosw inetsw_array[] =
    {
        {
            .type =       SOCK_STREAM,
            .protocol =   IPPROTO_TCP,
            .prot =       &tcp_prot,
            .ops =        &inet_stream_ops,
            .capability = -1,
            .no_check =   0,
            .flags =      INET_PROTOSW_PERMANENT,
        }
    }    
    这里最关键的是prot成员和ops成员,tcp_prot将提供TCP协议相关的全部操作,inet_stream_ops将提供域相关的全部操作,包括listen, connect等。
    3、socket->ops = 匹配到的那个ops。
    4、分配socket->sock。
    5、让struct inet_sock指向socket->sock,struct inet_sock是struct sock的超集。其头部内容即为struct sock。
    6、为inet_sock和socket->sock的成员赋初始值。这里,我们可以看到一些平时我们比较关心的问题,比如:inet->mc_ttl = 1。
    7、调用socket->sock->sk_prot->init(...)完成整个创建过程。
    最后,调用sock_map_fd找一个空闲的文件描述符,映射到这个创建好的套接字上,将这个文件描述符返回。
    描述到这里,一个最为粗糙的socket创建过程算是完成了,但留下的问题却更多了,它涉及到很多宠大的结构体,其内容与socket的正常工作都息息相关,下文会陆续给出分析。
21:49

struct sock详解
    结构体sock是套接口在网络层的表示,在代码include/net/sock.h 174行定义,下面是其内容:
    struct sock {
        struct sock_common  __sk_common;
#define sk_family       __sk_common.skc_family
#define sk_state        __sk_common.skc_state
#define sk_reuse        __sk_common.skc_reuse
#define sk_bound_dev_if     __sk_common.skc_bound_dev_if
#define sk_node         __sk_common.skc_node
#define sk_bind_node        __sk_common.skc_bind_node
#define sk_refcnt       __sk_common.skc_refcnt
        unsigned char       sk_shutdown : 2,
                            sk_no_check : 2,
                            sk_userlocks : 4;
        unsigned char       sk_protocol;
        unsigned short      sk_type;
        int         sk_rcvbuf;
        socket_lock_t       sk_lock;
        wait_queue_head_t   *sk_sleep;
        struct dst_entry    *sk_dst_cache;
        struct xfrm_policy  *sk_policy[2];
        rwlock_t        sk_dst_lock;
        atomic_t        sk_rmem_alloc;
        atomic_t        sk_wmem_alloc;
        atomic_t        sk_omem_alloc;
        struct sk_buff_head sk_receive_queue;
        struct sk_buff_head sk_write_queue;
        int         sk_wmem_queued;
        int         sk_forward_alloc;
        unsigned int        sk_allocation;
        int         sk_sndbuf;
        int         sk_route_caps;
        int         sk_hashent;
        unsigned long       sk_flags;
        unsigned long           sk_lingertime;
        struct {
            struct sk_buff *head;
            struct sk_buff *tail;
        } sk_backlog;
        struct sk_buff_head sk_error_queue;
        struct proto        *sk_prot;
        struct proto        *sk_prot_creator;
        rwlock_t        sk_callback_lock;
        int         sk_err,
                    sk_err_soft;
        unsigned short      sk_ack_backlog;
        unsigned short      sk_max_ack_backlog;
        __u32           sk_priority;
        struct ucred        sk_peercred;
        int         sk_rcvlowat;
        long            sk_rcvtimeo;
        long            sk_sndtimeo;
        struct sk_filter        *sk_filter;
        void            *sk_protinfo;
        struct timer_list   sk_timer;
        struct timeval      sk_stamp;
        struct socket       *sk_socket;
        void            *sk_user_data;
        struct page     *sk_sndmsg_page;
        struct sk_buff      *sk_send_head;
        __u32           sk_sndmsg_off;
        int         sk_write_pending;
        void            *sk_security;
        void            (*sk_state_change)(struct sock *sk);
        void            (*sk_data_ready)(struct sock *sk, int bytes);
        void            (*sk_write_space)(struct sock *sk);
        void            (*sk_error_report)(struct sock *sk);
        int             (*sk_backlog_rcv)(struct sock *sk,
                        struct sk_buff *skb);
        void            (*sk_destruct)(struct sock *sk);
    };
    __sk_common是套接口在网络层的最小表示。下面是其定义:
    struct sock_common {
        unsigned short      skc_family;         /*地址族*/
        volatile unsigned char  skc_state;      /*连接状态*/
        unsigned char       skc_reuse;          /*SO_REUSEADDR设置*/
        int         skc_bound_dev_if;
        struct hlist_node   skc_node;
        struct hlist_node   skc_bind_node;      /*哈希表相关*/
        atomic_t        skc_refcnt;             /*引用计数*/
    };
    sk_shutdown是一组标志位,SEND_SHUTDOWN and/or RCV_SHUTDOWN。
    sk_userlocks, SO_SNDBUF and SO_RCVBUF。
    sk_rcvbuf表示接收缓冲区的字节长度。
    sk_rmem_alloc表示接收队列已提交的字节数。
    sk_receive_queue表示接收的数据包的队列。
    sk_wmem_alloc表示发送队列已提交的字节数。
    sk_write_queue表示发送数据包的队列。
    sk_sndbuf表示发送缓冲区的字节长度。
    sk_flags,SO_LINGER (l_onoff),SO_BROADCAST,SO_KEEPALIVE,SO_OOBINLINE。
    sk_prot是指定的域内部的协议处理函数集,它是套接口层跟传输层之间的一个接口,提供诸如bind, accept, close等操作。
    sk_ack_backlog表示当前的侦听队列。
    sk_max_ack_backlog表示最大的侦听队列。
    sk_type表示套接字的类型,如SOCK_STREAM。
    sk_protocol表示在当前域中套接字所属的协议。
    几个函数指针均属回调函数,分别在套接口状态变化,有数据到达需要处理,有发送空间可用,有错误等时候被回调。最后一个函数sk_destruct在套接口释放时被回调。
Logo

更多推荐