博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TCP/IP源码(21)——struct inet_socks
阅读量:5869 次
发布时间:2019-06-19

本文共 3008 字,大约阅读时间需要 10 分钟。

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
    
在前面的博文中,我画出了TCP/IP数据包发送的流程图。现在开始学习TCP部分。今天由sock_aio_write开始。这是第一个进入TCP发送函数write会调用的第一个socket层的函数。
  1. static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
  2.              unsigned long nr_segs, loff_t pos)
  3. {
  4.     struct sock_iocb siocb, *x;
  5.     if (pos != 0)
  6.         return -ESPIPE;
     /* 申请sock iocb */
  1.     x = alloc_sock_iocb(iocb, &siocb);
  2.     if (!x)
  3.         return -ENOMEM;
  4.     return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
  5. }
从函数名字上看,这个函数是一个异步写函数。参数struct kiocb iocb不进行特殊说明了,因为它与TCP/IP协议栈没有直接联系,它存在与所有的I/O操作中。这个函数其实与TCP/IP并不太大联系,更多的是由于VFS。
那么根据前面博文中的流程图,直接跳到tcp_sendmsg,这个真正的TCP对应的4层发送函数。
  1. int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
  2.         size_t size)
  3. {
  4.     struct iovec *iov;
  5.     struct tcp_sock *tp = tcp_sk(sk);
  6.     struct sk_buff *skb;
  7.     int iovlen, flags;
  8.     int mss_now, size_goal;
  9.     int sg, err, copied;
  10.     long timeo;
     
      ...... ......
  1. }
与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为第一个成员变量。
  1. struct inet_sock {
  2.     /* sk and pinet6 has to be the first two members of inet_sock */
  3.     struct sock        sk;
  4. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  5.     struct ipv6_pinfo    *pinet6;
  6. #endif
  7.     /* Socket demultiplex comparisons on incoming packets. */
  8.     /* 
  9.     通过与下列的值比较,可以demultiplex收到的包。
  10.     通过系统调用connect,bind或setsocktopt可以设置下面的部分值。
  11.     */
  12.     __be32            inet_daddr;
  13.     __be32            inet_rcv_saddr;
  14.     __be16            inet_dport;
  15.     /* inet_num 为主机序的port,即inet_sport为其网络序格式 */
  16.     __u16            inet_num;
  17.     __be32            inet_saddr;
  18.     /* 用户指定的ttl值,如为-1,则使用系统默认值 */
  19.     __s16            uc_ttl;
  20.     __u16            cmsg_flags;
  21.     __be16            inet_sport;
  22.     __u16            inet_id;
/* ip option 信息*/
  1.     struct ip_options    *opt;
  2.     __u8            tos;
  3.     /* 
  4.     最小的ttl,可以通过/proc指定。
  5.     若收到的包的ttl小于该值,则drop掉该包
  6.     */
  7.     __u8            min_ttl;
  8.     /* 多播ttl */
  9.     __u8            mc_ttl;
  10.     /* 
  11.     PMTU value:   
  12. #define IP_PMTUDISC_DONT 0 /* Never send DF frames */
  13. #define IP_PMTUDISC_WANT 1 /* Use per route hints */
  14. #define IP_PMTUDISC_DO 2 /* Always DF */
  15. #define IP_PMTUDISC_PROBE 3       /* Ignore dst pmtu      */
  16.     */
  17.     __u8            pmtudisc;
  18.     /* 下面这些基本上都是socket的option */
  19.     __u8            recverr:1,
  20.                 is_icsk:1/* 是否是connection socket*/
  21.                 freebind:1/* 是否enable IP_FREEBIND option*/
  22.                 hdrincl:1/* 是否enable IP_HDRINCL option*/
  23.                 mc_loop:1,
  24.                 transparent:1,
  25.                 mc_all:1,
  26.                 nodefrag:1;
  27.     /* 多播网卡的索引 */
  28.     int            mc_index;
  29.     /* 用于发送的多播地址 */
  30.     __be32            mc_addr;
  31.     /* 所有加入的多播组 */
  32.     struct ip_mc_socklist    *mc_list;
  33.     /* cork 信息
  34.     主要用于分片时。具体应用请看前面的博文
  35.     */
  36.     struct {
  37.         unsigned int        flags;
  38.         unsigned int        fragsize;
  39.         struct ip_options    *opt;
  40.         struct dst_entry    *dst;
  41.         int            length; /* Total length of all frames */
  42.         __be32            addr;
  43.         struct flowi        fl;
  44.     } cork;
  45. };
从上面可以看出,struct inet_sock为TCP/IP协议栈极为重要的结构,它要位于所有的不同sock类型的顶部。主要用于保存不同socket类型公有的特性和信息。组织结构有些类似于C++的基类——尤其是内存布局上。
你可能感兴趣的文章
Linux设备模型(9)_device resource management ---devm申请空间【转】
查看>>
解决eclipse中出现Resource is out of sync with the file system问题
查看>>
Java学习——对象和类
查看>>
Atitit.php nginx页面空白 并返回500的解决
查看>>
struts2 OGNL表达式
查看>>
Andriod使用webview控件往APP里内嵌网页
查看>>
二级菜单不同方法的实现
查看>>
第五章 mybatis批量更新update
查看>>
pacific-atlantic-water-flow(不错)
查看>>
[LeetCode] Add Strings 字符串相加
查看>>
项目总结
查看>>
GUI(图形用户界面)
查看>>
PAC自动代理文件格式,教你如何写PAC文件
查看>>
ElasticSearch 组合过滤器
查看>>
ZooKeeper 了解
查看>>
Java里的并发容器与安全共享策略总结
查看>>
linux命令stat,查看文件详细信息
查看>>
win10 windows按钮右键没有命令提示符
查看>>
c#利用SWIG调用c++dll学习总结【转】
查看>>
英文名为什么最好不用joe?JOE英文名的寓意是什么?
查看>>