⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux-tcp ip源码阅读笔记.htm

📁 TCP/IP的源代码分析
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<DIV>/*yfhuang ipsec*/<BR>#ifdef 
CONFIG_IPSEC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;pfkey_init();<BR>#endif<BR>/*yfhuang 
ipsec*/<BR>}</DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG>&nbsp;&nbsp;&nbsp;&nbsp;2.2 
do_initcalls()</STRONG>&nbsp;中做了其它的初始化,其中包括</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;协议初始化,路由初始化,网络接口设备初始化</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG>(例如inet_init函数以_init开头表示是系统初始化时做,函数结束后跟module_init(inet_init),这是一个宏,在include/linux/init.c中定义,展开为_initcall(inet_init),表示这个函数在do_initcalls被调用了)</STRONG></DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG>&nbsp;&nbsp;&nbsp;&nbsp;2.3 协议初始化</STRONG></DIV>
<DIV><STRONG>此处主要列举inet协议的初始化过程。</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV>static int __init inet_init(void)<BR>{<BR>&nbsp;struct sk_buff 
*dummy_skb;<BR>&nbsp;struct inet_protocol *p;<BR>&nbsp;struct inet_protosw 
*q;<BR>&nbsp;struct list_head *r;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n");</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;if (sizeof(struct inet_skb_parm) &gt; sizeof(dummy_skb-&gt;cb)) 
{<BR>&nbsp;&nbsp;printk(KERN_CRIT "inet_proto_init: 
panic\n");<BR>&nbsp;&nbsp;return -EINVAL;<BR>&nbsp;}</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/*<BR>&nbsp; *&nbsp;Tell SOCKET that we are 
alive...&nbsp;注册socket,告诉socket inet类型的地址族已经准备好了<BR>&nbsp; */<BR>&nbsp;&nbsp; 
<BR>&nbsp; &nbsp;(void) sock_register(&amp;inet_family_ops);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/*<BR>&nbsp; *&nbsp;Add all the protocols. 
包括arp,ip、ICMP、UPD、tcp_v4、tcp、igmp的初始化,主要初始化各种协议对应的inode和socket变量。</DIV>
<DIV>&nbsp;</DIV>
<DIV>其中arp_init完成系统中路由部分neighbour表的初始化</DIV>
<DIV>&nbsp;</DIV>
<DIV>ip_init完成ip协议的初始化。在这两个函数中,都通过定义一个packet_type结构的变量将这种数据包对应的协议发送数据、允许发送设备都做初始化。</DIV>
<DIV><BR>&nbsp; */</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;printk(KERN_INFO "IP Protocols: ");<BR>&nbsp;for (p = 
inet_protocol_base; p != NULL;) {<BR>&nbsp;&nbsp;struct inet_protocol *tmp = 
(struct inet_protocol *) 
p-&gt;next;<BR>&nbsp;&nbsp;inet_add_protocol(p);<BR>&nbsp;&nbsp;printk("%s%s",p-&gt;name,tmp?", 
":"\n");<BR>&nbsp;&nbsp;p = tmp;<BR>&nbsp;}</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/* Register the socket-side information for inet_create. 
*/<BR>&nbsp;for(r = &amp;inetsw[0]; r &lt; &amp;inetsw[SOCK_MAX]; 
++r)<BR>&nbsp;&nbsp;INIT_LIST_HEAD(r);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;for(q = inetsw_array; q &lt; &amp;inetsw_array[INETSW_ARRAY_LEN]; 
++q)<BR>&nbsp;&nbsp;inet_register_protosw(q);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/*<BR>&nbsp; *&nbsp;Set the ARP module up&nbsp; <BR>&nbsp; */</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;arp_init();</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; &nbsp;/*<BR>&nbsp; &nbsp; *&nbsp;Set the IP module up<BR>&nbsp; 
&nbsp; */</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;ip_init();</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;tcp_v4_init(&amp;inet_family_ops);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/* Setup TCP slab cache for open requests. 
*/<BR>&nbsp;tcp_init();</DIV>
<DIV><BR>&nbsp;/*<BR>&nbsp; *&nbsp;Set the ICMP layer up<BR>&nbsp; */</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;icmp_init(&amp;inet_family_ops);</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/* I wish inet_add_protocol had no constructor 
hook...<BR>&nbsp;&nbsp;&nbsp; I had to move IPIP from net/ipv4/protocol.c :-( 
--ANK<BR>&nbsp; */<BR>#ifdef 
CONFIG_NET_IPIP<BR>&nbsp;ipip_init();<BR>#endif<BR>#ifdef 
CONFIG_NET_IPGRE<BR>&nbsp;ipgre_init();<BR>#endif</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/*<BR>&nbsp; *&nbsp;Initialise the multicast router<BR>&nbsp; 
*/<BR>#if defined(CONFIG_IP_MROUTE)<BR>&nbsp;ip_mr_init();<BR>#endif</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;/*<BR>&nbsp; *&nbsp;Create all the /proc entries.<BR>&nbsp; 
*/<BR>#ifdef CONFIG_PROC_FS<BR>&nbsp;proc_net_create ("raw", 0, 
raw_get_info);<BR>&nbsp;proc_net_create ("netstat", 0, 
netstat_get_info);<BR>&nbsp;proc_net_create ("snmp", 0, 
snmp_get_info);<BR>&nbsp;proc_net_create ("sockstat", 0, 
afinet_get_info);<BR>&nbsp;proc_net_create ("tcp", 0, 
tcp_get_info);<BR>&nbsp;proc_net_create ("udp", 0, 
udp_get_info);<BR>#endif&nbsp;&nbsp;/* CONFIG_PROC_FS */</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;ipfrag_init();</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;return 0;<BR>}&nbsp;&nbsp;&nbsp;</DIV>
<DIV>module_init(inet_init);<BR></DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG> 2.4 
路由初始化(包括neighbour表、FIB表、和路由缓存表的初始化工作)</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>2.4.1 
rtcache表 ip_rt_init()函数 
在net/ipv4/ip_output中调用,net/ipv4/route.c中定义</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>2.4.2 
FIB初始化 在ip_rt_init()中调用 在net/ipv4/fib_front.c中定义</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.4.3 
neigbour表初始化&nbsp;&nbsp;arp_init()函数中定义&nbsp;</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.5 网络接口设备初始化</STRONG></DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在系统中网络接口都是由一个dev_base链表进行管理的。通过内核的启动方式也是通过这个链表进行操作的。在系统启动之初,将所有内核能够支持的网络接口都初始化成这个链表中的一个节点,并且每个节点都需要初始化出init函数指针,用来检测网络接口设备。然后,系统遍历整个dev_base链表,对每个节点分别调用init函数指针,如果成功,证明网络接口设备可用,那么这个节点就可以进一步初始化,如果返回失败,那么证明该网络设备不存在或是不可用,只能将该节点删除。启动结束之后,在dev_base中剩下的都是可以用的网络接口设备。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.5.1 
do_initcalls----&gt;net_dev_init()(net/core/dev.c)------&gt;ethif_probe()(drivers/net/Space.c,在netdevice{}结构的init中调用,这边ethif_probe是以太网卡针对的调用)</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG>3.网络设备驱动程序(略)</STRONG></DIV>
<DIV><STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG>4.网络连接</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV><STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.1 连接的建立和关闭</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tcp连接建立的代码如下:</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server=gethostbyname(SERVER_NAME);</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sockfd=socket(AF_INET,SOCK_STREAM,0);</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address.sin_family=AF_INET;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address.sin_port=htons(PORT_NUM);</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memcpy(&amp;address.sin_addr,server-&gt;h_addr,server-&gt;h_length);</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connect(sockfd,&amp;address,sizeof(address));</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;连接的初始化与建立期间主要发生的事情如下:</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1)sys_socket调用:调用socket_creat(),创建出一个满足传入参数family、type、和protocol的socket,调用sock_map_fd()获取一个未被使用的文件描述符,并且申请并初始化对应的file{}结构。</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)sock_creat():创建socket结构,针对每种不同的family的socket结构的初始化,就需要调用不同的create函数来完成。对应于inet类型的地址来说,在网络协议初始化时调用sock_register()函数中完成注册的定义如下:</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct net_proto_family 
inet_family_ops={</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PF_INET;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inet_create</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};所以inet协议最后会调用inet_create函数。</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)inet_create: 
初始化sock的状态设置为SS_UNCONNECTED,申请一个新的sock结构,并且初始化socket的成员ops初始化为inet_stream_ops,而sock的成员prot初始化为tcp_prot。然后调用sock_init_data,将该socket结构的变量sock和sock类型的变量关联起来。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4)在系统初始化完毕后便是进行connect的工作,系统调用connect将一个和socket结构关联的文件描述符和一个sockaddr{}结构的地址对应的远程机器相关联,并且调用各个协议自己对应的connect连接函数。对应于tcp类型,则sock-&gt;ops-&gt;connect便为inet_stream_connect。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5)inet_stream_connect: 
得到sk,sk=sock-&gt;sk,锁定sk,对自动获取sk的端口号存放在sk-&gt;num中,并且用htons()函数转换存放在sk-&gt;sport中。然后调用sk-&gt;prot-&gt;connect()函数指针,对tcp协议来说就是tcp_v4_connect()函数。然后将sock-&gt;state状态字设置为SS_CONNECTING,等待后面一系列的处理完成之后,就将状态改成SS_CONNECTTED。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6) 
tcp_v4_connect():调用函数ip_route_connect(),寻找合适的路由存放在rt中。ip_route_connect找两次,第一次找到下一跳的ip地址,在路由缓存或fib中找到,然后第二次找到下一跳的具体邻居,到neigh_table中找到。然后申请出tcp头的空间存放在buff中。将sk中相关地址数据做一些针对路由的变动,并且初始化一个tcp连接的序列号,调用函数tcp_connect(),初始化tcp头,并设置tcp处理需要的定时器。一次connect()建立的过程就结束了。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;连接的关闭主要如下:</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1)close: 
一个socket文件描述符对应的file{}结构中,有一个file_operations{}结构的成员f_ops,它的初始化关闭函数为sock_close函数。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)sock_close:调用函数sock_release(),参数为一个socket{}结构的指针。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)sock_release:调用inet_release,并释放socket的指针和文件空间</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4)inet_release: 
调用和该socket对应协议的关闭函数inet_release,如果是tcp协议,那么调用的是tcp_close;最后释放sk。</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.2 
<STRONG>数据发送流程图</STRONG></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV>&nbsp;<IMG alt="" src="linux-Tcp IP源码阅读笔记.files/send.gif" useMap=#mymap 
border=0></DIV>
<DIV><STRONG></STRONG>&nbsp;</DIV>
<DIV>各层主要函数以及位置功能说明:</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1)sock_write:初始化msghdr{}结构 
net/socket.c</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)sock_sendmsg:net/socket.c</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)inet_sendmsg:net/ipv4/af_net.c</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4)tcp_sendmsg:申请sk_buff{}结构的空间,把msghdr{}结构中的数据填入sk_buff空间。net/ipv4/tcp.c</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5)tcp_send_skb:net/ipv4/tcp_output.c</DIV>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -