天天看點

TCP/IP源碼(21)——struct inet_socks

本文的copyleft歸[email protected]所有,使用GPL釋出,可以自由拷貝,轉載。但轉載請保持文檔的完整性,注明原作者及原連結,嚴禁用于任何商業用途。

作者:[email protected]

部落格:linuxfocus.blog.chinaunix.net    

在前面的博文中,我畫出了TCP/IP資料包發送的流程圖。現在開始學習TCP部分。今天由sock_aio_write開始。這是第一個進入TCP發送函數write會調用的第一個socket層的函數。

static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,

             unsigned long nr_segs, loff_t pos)

{

    struct sock_iocb siocb, *x;

    if (pos != 0)

        return -ESPIPE;

     /* 申請sock iocb */

    x = alloc_sock_iocb(iocb, &siocb);

    if (!x)

        return -ENOMEM;

    return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);

}

從函數名字上看,這個函數是一個異步寫函數。參數struct kiocb iocb不進行特殊說明了,因為它與TCP/IP協定棧沒有直接聯系,它存在與所有的I/O操作中。這個函數其實與TCP/IP并不太大聯系,更多的是由于VFS。

int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,

        size_t size)

    struct iovec *iov;

    struct tcp_sock *tp = tcp_sk(sk);

    struct sk_buff *skb;

    int iovlen, flags;

    int mss_now, size_goal;

    int sg, err, copied;

    long timeo;

      ...... ......

與UDP類似,對應于udp_sock,TCP也有struct tcp_sock。因為TCP的要比UDP複雜的多,是以這個tcp_sock也比udp_sock複雜龐大的多。這個struture非常複雜,超過160多行。不過幾乎每一個成員變量都有注釋,而我目前暫時也沒有能力添加更多的注釋,是以這裡就不粘貼代碼了。

不過我要對其中的struct inet_sock進行一點說明。在struct udp_sock中,struct inet_sock inet為其第一個成員變量。而對應struct tcp_sock,其第一個成員變量是struct inet_connection_sock inet_conn,不過struct inet_connection_sock inet_conn的第一個成員變量依然是struct inet_sock inet。是以無論是udp_sock還是tcp_sock,其記憶體布局上都保證了struct inet_sock inet為第一個成員變量。

struct inet_sock {

    /* sk and pinet6 has to be the first two members of inet_sock */

    struct sock        sk;

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)

    struct ipv6_pinfo    *pinet6;

#endif

    /* Socket demultiplex comparisons on incoming packets. */

    /* 

    通過與下列的值比較,可以demultiplex收到的包。

    通過系統調用connect,bind或setsocktopt可以設定下面的部分值。

    */

    __be32            inet_daddr;

    __be32            inet_rcv_saddr;

    __be16            inet_dport;

    /* inet_num 為主機序的port,即inet_sport為其網絡序格式 */

    __u16            inet_num;

    __be32            inet_saddr;

    /* 使用者指定的ttl值,如為-1,則使用系統預設值 */

    __s16            uc_ttl;

    __u16            cmsg_flags;

    __be16            inet_sport;

    __u16            inet_id;

/* ip option 資訊*/

    struct ip_options    *opt;

    __u8            tos;

    最小的ttl,可以通過/proc指定。

    若收到的包的ttl小于該值,則drop掉該包

    __u8            min_ttl;

    /* 多點傳播ttl */

    __u8            mc_ttl;

    PMTU value:   

#define IP_PMTUDISC_DONT 0 /* Never send DF frames */

#define IP_PMTUDISC_WANT 1 /* Use per route hints */

#define IP_PMTUDISC_DO 2 /* Always DF */

#define IP_PMTUDISC_PROBE 3       /* Ignore dst pmtu      */

    __u8            pmtudisc;

    /* 下面這些基本上都是socket的option */

    __u8            recverr:1,

                is_icsk:1, /* 是否是connection socket*/

                freebind:1, /* 是否enable IP_FREEBIND option*/

                hdrincl:1, /* 是否enable IP_HDRINCL option*/

                mc_loop:1,

                transparent:1,

                mc_all:1,

                nodefrag:1;

    /* 多點傳播網卡的索引 */

    int            mc_index;

    /* 用于發送的多點傳播位址 */

    __be32            mc_addr;

    /* 所有加入的多點傳播組 */

    struct ip_mc_socklist    *mc_list;

    /* cork 資訊

    struct {

        unsigned int        flags;

        unsigned int        fragsize;

        struct ip_options    *opt;

        struct dst_entry    *dst;

        int            length; /* Total length of all frames */

        __be32            addr;

        struct flowi        fl;

    } cork;

};

從上面可以看出,struct inet_sock為TCP/IP協定棧極為重要的結構,它要位于所有的不同sock類型的頂部。主要用于儲存不同socket類型公有的特性和資訊。組織結構有些類似于C++的基類——尤其是記憶體布局上。

繼續閱讀