linux-Tcp IP協(xié)議棧源碼閱讀筆記
《linux-Tcp IP協(xié)議棧源碼閱讀筆記》由會(huì)員分享,可在線閱讀,更多相關(guān)《linux-Tcp IP協(xié)議棧源碼閱讀筆記(17頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、linux-Tcp IP協(xié)議棧源碼閱讀筆記 一.linux內(nèi)核網(wǎng)絡(luò)棧代碼的準(zhǔn)備知識(shí) 1. linux內(nèi)核ipv4網(wǎng)絡(luò)部分分層結(jié)構(gòu): BSD socket層: 這一部分處理BSD socket相關(guān)操作,每個(gè)socket在內(nèi)核中以struct socket結(jié)構(gòu)體現(xiàn)。這一部分的文件 主要有:/net/socket.c /net/protocols.c etc INET socket層:BSD socket是個(gè)可以用于各種網(wǎng)絡(luò)協(xié)議的接口,而當(dāng)用于tcp/ip,即建立了AF_INET形式的socket時(shí), 還需要保留些額外的參數(shù),于是就有了struct soc
2、k結(jié)構(gòu)。文件主要 有:/net/ipv4/protocol.c /net/ipv4/af_inet.c /net/core/sock.c etc TCP/UDP層:處理傳輸層的操作,傳輸層用struct inet_protocol和struct proto兩個(gè)結(jié)構(gòu)表示。文件主要 有:/net/ipv4/udp.c /net/ipv4/datagram.c /net/ipv4/tcp.c /net/ipv4/tcp_input.c /net/ipv4//tcp_output.c /net/ipv4/tcp_minisocks.c /net/ipv4/tcp_output.c/n
3、et/ipv4/tcp_timer.c etc IP層:處理網(wǎng)絡(luò)層的操作,網(wǎng)絡(luò)層用struct packet_type結(jié)構(gòu)表示。文件主要有:/net/ipv4/ip_forward.c ip_fragment.c ip_input.c ip_output.c etc. 數(shù)據(jù)鏈路層和驅(qū)動(dòng)程序:每個(gè)網(wǎng)絡(luò)設(shè)備以struct net_device表示,通用的處理在dev.c中,驅(qū)動(dòng)程序都在/driver/net目 錄下。 2. 兩臺(tái)主機(jī)建立udp通信所走過(guò)的函數(shù)列表 ^ |sys_readfs/read_write.c |sock_readnet/socket
4、.c |sock_recvmsgnet/socket.c |inet_recvmsgnet/ipv4/af_inet.c |udp_recvmsgnet/ipv4/udp.c |skb_recv_datagramnet/core/datagram.c |------------------------------------------- |sock_queue_rcv_skbinclude/net/sock.h |udp_queue_rcv_skbnet/ipv4/udp.c |udp_rcvnet/ipv4/udp.c |ip_local_deliver_finish n
5、et/ipv4/ip_input.c |ip_local_delivernet/ipv4/ip_input.c |ip_recvnet/ipv4/ip_input.c |net_rx_actionnet/dev.c |------------------------------------------- |netif_rxnet/dev.c |el3_rxdriver/net/3c309.c |el3_interruptdriver/net/3c309.c ========================== |sys_writefs/read_write.c |s
6、ock_writevnet/socket.c |sock_sendmsgnet/socket.c |inet_sendmsgnet/ipv4/af_inet.c |udp_sendmsgnet/ipv4/udp.c |ip_build_xmitnet/ipv4/ip_output.c |output_maybe_reroutenet/ipv4/ip_output.c |ip_outputnet/ipv4/ip_output.c |ip_finish_outputnet/ipv4/ip_output.c |dev_queue_xmitnet/dev.c |-----------
7、--------------------------------- |el3_start_xmitdriver/net/3c309.c V 3. 網(wǎng)絡(luò)路徑圖、重要數(shù)據(jù)結(jié)構(gòu)sk_buffer及路由介紹 linux-net.pdf 第2.1章 第2.3章 第2.4章 4. 從連接、發(fā)送、到接收數(shù)據(jù)包的過(guò)程 linux-net.pdf 第4、5、6章詳細(xì)闡述 二.linux的tcp-ip棧代碼的詳細(xì)分析 1.數(shù)據(jù)結(jié)構(gòu)(msghdr,sk_buff,socket,sock,proto_ops,proto) bsd套接字層,操作的對(duì)象是socket,數(shù)據(jù)存放
8、在msghdr這樣的數(shù)據(jù)結(jié)構(gòu): 創(chuàng)建socket需要傳遞family,type,protocol三個(gè)參數(shù),創(chuàng)建socket其實(shí)就是創(chuàng)建一個(gè)socket實(shí)例,然后創(chuàng)建一個(gè)文件描述符結(jié)構(gòu),并且互相建立一些關(guān)聯(lián),即建立互相連接的指針,并且初始化這些對(duì)文件的寫讀操作映射到socket的read,write函數(shù)上來(lái)。 同時(shí)初始化socket的操作函數(shù)(proto_ops結(jié)構(gòu)),如果傳入的type參數(shù)是STREAM類型,那么就初始化為 SOCKET->ops為inet_stream_ops,如果是DGRAM類型,則SOCKET-ops為inet_dgram_ops。對(duì)于 inet_stream
9、_ops其實(shí)是一個(gè)結(jié)構(gòu)體,包含了stream類型的socket操作的一些入口函數(shù),在這些函數(shù)里主要做的是對(duì)socket進(jìn)行相關(guān)的操作,同時(shí)通過(guò)調(diào)用下面提到的sock中的相關(guān)操作完成socket到sock層的傳遞。比如在inet_stream_ops里有個(gè) inet_release的操作,這個(gè)操作除了釋放socket的類型空間操作外,還通過(guò)調(diào)用socket連接的sock的close操作,對(duì)于 stream類型來(lái)說(shuō),即tcp_close來(lái)關(guān)閉sock 釋放sock。 創(chuàng)建socket同時(shí)還創(chuàng)建sock數(shù)據(jù)空間,初始化sock,初始化過(guò)程主要做的事情是初始化三個(gè)隊(duì)列,receive_queu
10、e(接收到的數(shù)據(jù)包sk_buff鏈表隊(duì)列),send_queue(需要發(fā)送數(shù)據(jù)包的sk_buff鏈表隊(duì)列),backlog_queue(主要用于tcp中三次握手成功的那些數(shù)據(jù)包,自己猜的),根據(jù)family、type參數(shù),初始化sock的操作,比如對(duì)于family為inet類型的,type為 stream類型的,sock->proto初始化為tcp_prot.其中包括stream類型的協(xié)議sock操作對(duì)應(yīng)的入口函數(shù)。 在一端對(duì)socket進(jìn)行write的過(guò)程中,首先會(huì)把要write的字符串緩沖區(qū)整理成msghdr的數(shù)據(jù)結(jié)構(gòu)形式(參見(jiàn)linux內(nèi)核 2.4版源代碼分析大全),然后調(diào)用soc
11、k_sendmsg把msghdr的數(shù)據(jù)傳送至inet層,對(duì)于msghdr結(jié)構(gòu)中數(shù)據(jù)區(qū)中的每個(gè)數(shù)據(jù)包,創(chuàng)建 sk_buff結(jié)構(gòu),填充數(shù)據(jù),掛至發(fā)送隊(duì)列。一層層往下層協(xié)議傳遞。一下每層協(xié)議不再對(duì)數(shù)據(jù)進(jìn)行拷貝。而是對(duì)sk_buff結(jié)構(gòu)進(jìn)行操作。 inet套接字及以下層 數(shù)據(jù)存放在sk_buff這樣的數(shù)據(jù)結(jié)構(gòu)里: 路由: 在linux的路由系統(tǒng)主要保存了三種與路由相關(guān)的數(shù)據(jù),第一種是在物理上和本機(jī)相連接的主機(jī)地址信息表,第二種是保存了在網(wǎng)絡(luò)訪問(wèn)中判斷一個(gè)網(wǎng)絡(luò)地址應(yīng)該走什么路由的數(shù)據(jù)表;第三種是最新使用過(guò)的查詢路由地址的緩存地址數(shù)據(jù)表。 1.neighbour結(jié)構(gòu) neighbour
12、_table{ }是一個(gè)包含和本機(jī)所連接的所有鄰元素的信息的數(shù)據(jù)結(jié)構(gòu)。該結(jié)構(gòu)中有個(gè)元素是neighbour結(jié)構(gòu)的數(shù)組,數(shù)組的每一個(gè)元素都是一個(gè)對(duì)應(yīng)于鄰機(jī)的 neighbour結(jié)構(gòu),系統(tǒng)中由于協(xié)議的不同,會(huì)有不同的判斷鄰居的方式,每種都有neighbour_table{}類型的實(shí)例,這些實(shí)例是通過(guò) neighbour_table{}中的指針next串聯(lián)起來(lái)的。在neighbour結(jié)構(gòu)中,包含有與該鄰居相連的網(wǎng)絡(luò)接口設(shè)備net_device的指針,網(wǎng)絡(luò)接口的硬件地址,鄰居的硬件地址,包含有neigh_ops{}指針,這些函數(shù)指針是直接用來(lái)連接傳輸數(shù)據(jù)的,包含有 queue_xmit(struct
13、* sk_buff)函數(shù)入口地址,這個(gè)函數(shù)可能會(huì)調(diào)用硬件驅(qū)動(dòng)程序的發(fā)送函數(shù)。 2.FIB結(jié)構(gòu)在FIB中保存的是最重要的路由規(guī)則,通過(guò)對(duì)FIB數(shù)據(jù)的查找和換算,一定能夠獲得路由一個(gè)地址的方法。系統(tǒng)中路由一般采取的手段是:先到路由緩存中查找表項(xiàng),如果能夠找到,直接對(duì)應(yīng)的一項(xiàng)作為路由的規(guī)則;如果不能找到,那么就到FIB中根據(jù)規(guī)則換算傳算出來(lái),并且增加一項(xiàng)新的,在路由緩存中將項(xiàng)目添加進(jìn)去。 3.route結(jié)構(gòu)(即路由緩存中的結(jié)構(gòu)) 數(shù)據(jù)鏈路層: net_device{}結(jié)構(gòu),對(duì)應(yīng)于每一個(gè)網(wǎng)絡(luò)接口設(shè)備。這個(gè)結(jié)構(gòu)中包含很多可以直接獲取網(wǎng)卡信息的函數(shù)和變量,同時(shí)包含很多對(duì)于網(wǎng)
14、卡操作的函數(shù),這些直接指向該網(wǎng)卡驅(qū)動(dòng)程序的許多函數(shù)入口,包括發(fā)送接收數(shù)據(jù)幀到緩沖區(qū)等。當(dāng)這些完成后,比如數(shù)據(jù)接收到緩沖區(qū)后便由netif_rx(在net/core /dev.c各種設(shè)備驅(qū)動(dòng)程序的上層框架程序)把它們組成sk_buff形式掛到系統(tǒng)接收的backlog隊(duì)列然后交由上層網(wǎng)絡(luò)協(xié)議處理。同樣,對(duì)于上層協(xié)議處理下來(lái)的那些sk_buff。便由dev_queue_xmit函數(shù)放入網(wǎng)絡(luò)緩沖區(qū),交給網(wǎng)卡驅(qū)動(dòng)程序的發(fā)送程序處理。 在系統(tǒng)中存在一張鏈表dev_base將系統(tǒng)中所有的net_device{}結(jié)構(gòu)連在一起。對(duì)應(yīng)于內(nèi)核初始化而言,系統(tǒng)啟動(dòng)時(shí)便為每個(gè)所有可能支持的網(wǎng)絡(luò)接口設(shè)備申請(qǐng)了一個(gè)
15、net_device{}空間并串連起來(lái),然后對(duì)每個(gè)接點(diǎn)運(yùn)行檢測(cè)過(guò)程,如果檢測(cè)成功,則在dev_base鏈表中保留這個(gè)接點(diǎn),否則刪除。對(duì)應(yīng)于模塊加載來(lái)說(shuō),則是調(diào)用register_netdev()注冊(cè)net_device,在這個(gè)函數(shù)中運(yùn)行檢測(cè)過(guò)程,如果成功,則加到 dev_base鏈表。否則就返回檢測(cè)不到信息。刪除同理,調(diào)用 unregister_netdev。 2.啟動(dòng)分析 2.1 初始化進(jìn)程 :start-kernel(main.c)---->do_basic_setup(main.c)---->sock_init(/net/socket.c)---->do_initcalls
16、(main.c) void __init sock_init(void) { int i; printk(KERN_INFO "Linux NET4.0 for Linux 2.4\n"); printk(KERN_INFO "Based upon Swansea University Computer Society NET3.039\n"); /* *Initialize all address (protocol) families. 每一項(xiàng)表示的是針對(duì)一個(gè)地址族的操作集合,例如對(duì)于ipv4來(lái)說(shuō),在net/ipv4/af_inet.c文件中的函數(shù) inet_p
17、roto_init()就調(diào)用sock_register()函數(shù)將inet_families_ops初始化到屬于IPV4的 net_families數(shù)組中的一項(xiàng)。 */ for (i = 0; i < NPROTO; i++) net_families[i] = NULL; /* *Initialize sock SLAB cache.初始化對(duì)于sock結(jié)構(gòu)預(yù)留的內(nèi)存的slab緩存。 */ sk_init(); #ifdef SLAB_SKB /* *Initialize skbuff SLAB cache 初始化對(duì)于skbuff結(jié)構(gòu)的slab緩
18、存。以后對(duì)于skbuff的申請(qǐng)可以通過(guò)函數(shù)kmem_cache_alloc()在這個(gè)緩存中申請(qǐng)空間。 */ skb_init(); #endif /* *Wan router layer. */ #ifdef CONFIG_WAN_ROUTER wanrouter_init(); #endif /* *Initialize the protocols module.向系統(tǒng)登記sock文件系統(tǒng),并且將其安裝到系統(tǒng)上來(lái)。 */ register_filesystem(&sock_fs_type); sock_mnt = kern_mount
19、(&sock_fs_type); /* The real protocol initialization is performed when * do_initcalls is run. */ /* * The netlink device handler may be needed early. */ #ifdef CONFIG_NET rtnetlink_init(); #endif #ifdef CONFIG_NETLINK_DEV init_netlink(); #endif #ifdef CONFIG_NETFILTER netfilte
20、r_init(); #endif #ifdef CONFIG_BLUEZ bluez_init(); #endif /*yfhuang ipsec*/ #ifdef CONFIG_IPSEC pfkey_init(); #endif /*yfhuang ipsec*/ } 2.2 do_initcalls()中做了其它的初始化,其中包括 協(xié)議初始化,路由初始化,網(wǎng)絡(luò)接口設(shè)備初始化 (例如inet_init函數(shù)以_init開(kāi)頭表示是系統(tǒng)初始化時(shí)做,函數(shù)結(jié)束后跟 module_init(inet_init),這是一個(gè)宏,在include/linux
21、/init.c中定義,展開(kāi)為 _initcall(inet_init),表示這個(gè)函數(shù)在do_initcalls被調(diào)用了) 2.3 協(xié)議初始化 此處主要列舉inet協(xié)議的初始化過(guò)程。 static int __init inet_init(void) { struct sk_buff *dummy_skb; struct inet_protocol *p; struct inet_protosw *q; struct list_head *r; printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n"); i
22、f (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "inet_proto_init: panic\n"); return -EINVAL; } /* *Tell SOCKET that we are alive...注冊(cè)socket,告訴socket inet類型的地址族已經(jīng)準(zhǔn)備好了 */ (void) sock_register(&inet_family_ops); /* *Add all the protocols. 包括arp,ip、ICMP、UP
23、D、tcp_v4、tcp、igmp的初始化,主要初始化各種協(xié)議對(duì)應(yīng)的inode和socket變量。 其中arp_init完成系統(tǒng)中路由部分neighbour表的初始化 ip_init完成ip協(xié)議的初始化。在這兩個(gè)函數(shù)中,都通過(guò)定義一個(gè)packet_type結(jié)構(gòu)的變量將這種數(shù)據(jù)包對(duì)應(yīng)的協(xié)議發(fā)送數(shù)據(jù)、允許發(fā)送設(shè)備都做初始化。 */ printk(KERN_INFO "IP Protocols: "); for (p = inet_protocol_base; p != NULL;) { struct inet_protocol *tmp = (struct inet_
24、protocol *) p->next; inet_add_protocol(p); printk("%s%s",p->name,tmp?", ":"\n"); p = tmp; } /* Register the socket-side information for inet_create. */ for(r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) INIT_LIST_HEAD(r); for(q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) inet
25、_register_protosw(q); /* *Set the ARP module up */ arp_init(); /* *Set the IP module up */ ip_init(); tcp_v4_init(&inet_family_ops); /* Setup TCP slab cache for open requests. */ tcp_init(); /* *Set the ICMP layer up */ icmp_init(&inet_family_ops); /* I wi
26、sh inet_add_protocol had no constructor hook... I had to move IPIP from net/ipv4/protocol.c :-( --ANK */ #ifdef CONFIG_NET_IPIP ipip_init(); #endif #ifdef CONFIG_NET_IPGRE ipgre_init(); #endif /* *Initialise the multicast router */ #if defined(CONFIG_IP_MROUTE) ip_mr_init(); #end
27、if /* *Create all the /proc entries. */ #ifdef CONFIG_PROC_FS proc_net_create ("raw", 0, raw_get_info); proc_net_create ("netstat", 0, netstat_get_info); proc_net_create ("snmp", 0, snmp_get_info); proc_net_create ("sockstat", 0, afinet_get_info); proc_net_create ("tcp", 0, tcp_get_info
28、); proc_net_create ("udp", 0, udp_get_info); #endif/* CONFIG_PROC_FS */ ipfrag_init(); return 0; } module_init(inet_init); 2.4 路由初始化(包括neighbour表、FIB表、和路由緩存表的初始化工作) 2.4.1 rtcache表 ip_rt_init()函數(shù) 在net/ipv4/ip_output中調(diào)用,net/ipv4/route.c中定義 2.4.2 FIB初始化 在ip_rt_init()中調(diào)用 在net/ipv4/
29、fib_front.c中定義 2.4.3 neigbour表初始化arp_init()函數(shù)中定義 2.5 網(wǎng)絡(luò)接口設(shè)備初始化 在系統(tǒng)中網(wǎng)絡(luò)接口都是由一個(gè)dev_base鏈表進(jìn)行管理的。通過(guò)內(nèi)核的啟動(dòng)方式也是通過(guò)這個(gè)鏈表進(jìn)行操作的。在系統(tǒng)啟動(dòng)之初,將所有內(nèi)核能夠支持的網(wǎng)絡(luò)接口都初始化成這個(gè)鏈表中的一個(gè)節(jié)點(diǎn),并且每個(gè)節(jié)點(diǎn)都需要初始化出init函數(shù)指針,用來(lái)檢測(cè)網(wǎng)絡(luò)接口設(shè)備。然后,系統(tǒng)遍歷整個(gè)dev_base鏈表,對(duì)每個(gè)節(jié)點(diǎn)分別調(diào)用init函數(shù)指針,如果成功,證明網(wǎng)絡(luò)接口設(shè)備可用,那么這個(gè)節(jié)點(diǎn)就可以進(jìn)一步初始化,如果返回失敗,那么證明該網(wǎng)絡(luò)設(shè)備不存在或是不可用,只能將該節(jié)點(diǎn)刪除。啟
30、動(dòng)結(jié)束之后,在dev_base中剩下的都是可以用的網(wǎng)絡(luò)接口設(shè)備。 2.5.1 do_initcalls---->net_dev_init()(net/core /dev.c)------>ethif_probe()(drivers/net/Space.c,在netdevice{}結(jié)構(gòu)的init中調(diào)用,這邊ethif_probe是以太網(wǎng)卡針對(duì)的調(diào)用) 3.網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序(略) 4.網(wǎng)絡(luò)連接 4.1 連接的建立和關(guān)閉 tcp連接建立的代碼如下: server=gethostbyname(SERVER_NAME); sockfd=socket(AF_I
31、NET,SOCK_STREAM,0); address.sin_family=AF_INET; address.sin_port=htons(PORT_NUM); memcpy(&address.sin_addr,server->h_addr,server->h_length); connect(sockfd,&address,sizeof(address)); 連接的初始化與建立期間主要發(fā)生的事情如下: 1)sys_socket調(diào)用:調(diào)用socket_creat(),創(chuàng)建出一個(gè)滿足傳入?yún)?shù)family、type、和 protocol的socket,調(diào)用sock_map_f
32、d()獲取一個(gè)未被使用的文件描述符,并且申請(qǐng)并初始化對(duì)應(yīng)的file{}結(jié)構(gòu)。 2)sock_creat():創(chuàng)建socket結(jié)構(gòu),針對(duì)每種不同的family的socket結(jié)構(gòu)的初始化,就需要調(diào)用不同的create函數(shù)來(lái)完成。對(duì)應(yīng)于inet類型的地址來(lái)說(shuō),在網(wǎng)絡(luò)協(xié)議初始化時(shí)調(diào)用sock_register()函數(shù)中完成注冊(cè)的定義如下: struct net_proto_family inet_family_ops={ PF_INET; inet_create };所以inet協(xié)議最后會(huì)調(diào)用inet_create函數(shù)。 3)inet_create: 初始化sock的狀態(tài)設(shè)置為SS
33、_UNCONNECTED,申請(qǐng)一個(gè)新的sock結(jié)構(gòu),并且初始化socket的成員ops初始化為 inet_stream_ops,而sock的成員prot初始化為tcp_prot。然后調(diào)用sock_init_data,將該socket結(jié)構(gòu)的變量sock和sock類型的變量關(guān)聯(lián)起來(lái)。 4)在系統(tǒng)初始化完畢后便是進(jìn)行connect的工作,系統(tǒng)調(diào)用connect將一個(gè)和socket結(jié)構(gòu)關(guān)聯(lián)的文件描述符和一個(gè) sockaddr{}結(jié)構(gòu)的地址對(duì)應(yīng)的遠(yuǎn)程機(jī)器相關(guān)聯(lián),并且調(diào)用各個(gè)協(xié)議自己對(duì)應(yīng)的connect連接函數(shù)。對(duì)應(yīng)于tcp類型,則 sock->ops->connect便為inet_stream_c
34、onnect。 5)inet_stream_connect: 得到sk,sk=sock->sk,鎖定sk,對(duì)自動(dòng)獲取sk的端口號(hào)存放在sk->num中,并且用htons()函數(shù)轉(zhuǎn)換存放在sk-& gt;sport中。然后調(diào)用sk->prot->connect()函數(shù)指針,對(duì)tcp協(xié)議來(lái)說(shuō)就是tcp_v4_connect()函數(shù)。然后將sock->state狀態(tài)字設(shè)置為SS_CONNECTING,等待后面一系列的處理完成之后,就將狀態(tài)改成 SS_CONNECTTED。 6) tcp_v4_connect():調(diào)用函數(shù)ip_route_connect(),尋找合適的路由存放在rt中。i
35、p_route_connect找兩次,第一次找到下一跳的ip地址,在路由緩存或fib中找到,然后第二次找到下一跳的具體鄰居,到neigh_table中找到。然后申請(qǐng)出tcp頭的空間存放在buff中。將sk中相關(guān)地址數(shù)據(jù)做一些針對(duì)路由的變動(dòng),并且初始化一個(gè)tcp連接的序列號(hào),調(diào)用函數(shù)tcp_connect(),初始化tcp 頭,并設(shè)置tcp處理需要的定時(shí)器。一次connect()建立的過(guò)程就結(jié)束了。 連接的關(guān)閉主要如下: 1)close: 一個(gè)socket文件描述符對(duì)應(yīng)的file{}結(jié)構(gòu)中,有一個(gè)file_operations{}結(jié)構(gòu)的成員f_ops,它的初始化關(guān)閉函數(shù)為sock_c
36、lose函數(shù)。 2)sock_close:調(diào)用函數(shù)sock_release(),參數(shù)為一個(gè)socket{}結(jié)構(gòu)的指針。 3)sock_release:調(diào)用inet_release,并釋放socket的指針和文件空間 4)inet_release: 調(diào)用和該socket對(duì)應(yīng)協(xié)議的關(guān)閉函數(shù)inet_release,如果是tcp協(xié)議,那么調(diào)用的是tcp_close;最后釋放sk。 4.2 數(shù)據(jù)發(fā)送流程圖 各層主要函數(shù)以及位置功能說(shuō)明: 1)sock_write:初始化msghdr{}結(jié)構(gòu) net/socket.c 2)sock_sendmsg:net/soc
37、ket.c 3)inet_sendmsg:net/ipv4/af_net.c 4)tcp_sendmsg:申請(qǐng)sk_buff{}結(jié)構(gòu)的空間,把msghdr{}結(jié)構(gòu)中的數(shù)據(jù)填入sk_buff空間。net/ipv4/tcp.c 5)tcp_send_skb:net/ipv4/tcp_output.c 6)tcp_transmit_skb:net/ipv4/tcp_output.c 7)ip_queue_xmit:net/ipv4/ip_output.c 8)ip_queue_xmit2:net/ipv4/ip_output.c 9)ip_output:net/ipv4/ip_outp
38、ut.c 10)ip_finish_output:net/ipv4/ip_output.c 11)ip_finish_output2:net/ipv4/ip_output.c 12)neigh_resolve_output:net/core/neighbour.c 13)dev_queue_xmit:net/core/dev.c 4.3 數(shù)據(jù)接收流程圖 各層主要函數(shù)以及位置功能說(shuō)明: 1)sock_read:初始化msghdr{}的結(jié)構(gòu)類型變量msg,并且將需要接收的數(shù)據(jù)存放的地址傳給msg.msg_iov->iov_base. net/socket.c 2)s
39、ock_recvmsg: 調(diào)用函數(shù)指針sock->ops->recvmsg()完成在INET Socket層的數(shù)據(jù)接收過(guò)程.其中sock->ops被初始化為inet_stream_ops,其成員recvmsg對(duì)應(yīng)的函數(shù)實(shí)現(xiàn)為 inet_recvmsg()函數(shù). net/socket.c 3)sys_recv()/sys_recvfrom():分別對(duì)應(yīng)著面向連接和面向無(wú)連接的協(xié)議兩種情況. net/socket.c 4)inet_recvmsg:調(diào)用sk->prot->recvmsg函數(shù)完成數(shù)據(jù)接收,這個(gè)函數(shù)對(duì)于tcp協(xié)議便是tcp_recvmsg net/ipv4/af_net.c 5)
40、tcp_recvmsg:從網(wǎng)絡(luò)協(xié)議棧接收數(shù)據(jù)的動(dòng)作,自上而下的觸發(fā)動(dòng)作一直到這個(gè)函數(shù)為止,出現(xiàn)了一次等待的過(guò)程.函數(shù)tcp_recvmsg可能會(huì)被動(dòng)地等待在sk的接收數(shù)據(jù)隊(duì)列上,也就是說(shuō),系統(tǒng)中肯定有其他地方會(huì)去修改這個(gè)隊(duì)列使得tcp_recvmsg可以進(jìn)行下去.入口參數(shù)sk是這個(gè)網(wǎng)絡(luò)連接對(duì)應(yīng)的sock{}指針,msg用于存放接收到的數(shù)據(jù).接收數(shù)據(jù)的時(shí)候會(huì)去遍歷接收隊(duì)列中的數(shù)據(jù),找到序列號(hào)合適的. 但讀取隊(duì)列為空時(shí)tcp_recvmsg就會(huì)調(diào)用tcp_v4_do_rcv使用backlog隊(duì)列填充接收隊(duì)列. 6)tcp_v4_rcv:tcp_v4_rcv被ip_local_deliver函數(shù)
41、調(diào)用,是從IP層協(xié)議向INET Socket層提交的"數(shù)據(jù)到"請(qǐng)求,入口參數(shù)skb存放接收到的數(shù)據(jù),len是接收的數(shù)據(jù)的長(zhǎng)度,這個(gè)函數(shù)首先移動(dòng)skb->data指針,讓它指向tcp頭,然后更新tcp層的一些數(shù)據(jù)統(tǒng)計(jì),然后進(jìn)行tcp的一些值的校驗(yàn).再?gòu)腎NET Socket層中已經(jīng)建立的sock{}結(jié)構(gòu)變量中查找正在等待當(dāng)前到達(dá)數(shù)據(jù)的哪一項(xiàng).可能這個(gè)sock{}結(jié)構(gòu)已經(jīng)建立,或者還處于監(jiān)聽(tīng)端口、等待數(shù)據(jù)連接的狀態(tài)。返回的sock結(jié)構(gòu)指針存放在sk中。然后根據(jù)其他進(jìn)程對(duì)sk的操作情況,將skb發(fā)送到合適的位置.調(diào)用如下: TCP包接收器(tcp_v4_rcv)將TCP包投遞到目的套接字進(jìn)行接
42、收處理. 當(dāng)套接字正被用戶鎖定,TCP包將暫時(shí)排入該套接字的后備隊(duì)列(sk_add_backlog).這時(shí)如果某一用戶線程企圖鎖定該套接字 (lock_sock),該線程被排入套接字的后備處理等待隊(duì)列(sk->lock.wq).當(dāng)用戶釋放上鎖的套接字時(shí) (release_sock,在tcp_recvmsg中調(diào)用),后備隊(duì)列中的TCP包被立即注入TCP包處理器(tcp_v4_do_rcv)進(jìn)行處理,然后喚醒等待隊(duì)列中最先的一個(gè)用戶來(lái)獲得其鎖定權(quán). 如果套接字未被上鎖,當(dāng)用戶正在讀取該套接字時(shí), TCP包將被排入套接字的預(yù)備隊(duì)列(tcp_prequeue),將其傳遞到該用戶線程上下文中進(jìn)行處理.如
43、果添加到sk->prequeue不成功,便可以添加到 sk->receive_queue隊(duì)列中(用戶線程可以登記到預(yù)備隊(duì)列,當(dāng)預(yù)備隊(duì)列中出現(xiàn)第一個(gè)包時(shí)就喚醒等待線程.) /net/tcp_ipv4.c 7)ip_rcv、ip_rcv_finish:從以太網(wǎng)接收數(shù)據(jù),放到skb里,作ip層的一些數(shù)據(jù)及選項(xiàng)檢查,調(diào)用 ip_route_input()做路由處理,判斷是進(jìn)行ip轉(zhuǎn)發(fā)還是將數(shù)據(jù)傳遞到高一層的協(xié)議.調(diào)用skb->dst->input函數(shù)指針,這個(gè)指針的實(shí)現(xiàn)可能有多種情況,如果路由得到的結(jié)果說(shuō)明這個(gè)數(shù)據(jù)包應(yīng)該轉(zhuǎn)發(fā)到其他主機(jī),這里的input便是ip_forward;如果數(shù)據(jù)包是給本機(jī)的,那么input指針初始化為ip_local_deliver函數(shù)./net/ipv4/ip_input.c 8)ip_local_deliver、ip_local_deliver_finish:入口參數(shù)skb存放需要傳送到上層協(xié)議的數(shù)據(jù),從ip頭中獲取是否已經(jīng)分拆的信息,如果已經(jīng)分拆,則調(diào)用函數(shù)ip_defrag將數(shù)據(jù)包重組。然后通過(guò)調(diào)用 ip_prot->handler指針調(diào)用tcp_v4_rcv(tcp)。ip_prot是inet_protocol結(jié)構(gòu)指針,是用來(lái)ip層登記協(xié)議的,比如由udp,tcp,icmp等協(xié)議。 /net/ipv4/ip_input.c
- 溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 市教育局冬季運(yùn)動(dòng)會(huì)安全工作預(yù)案
- 2024年秋季《思想道德與法治》大作業(yè)及答案3套試卷
- 2024年教師年度考核表個(gè)人工作總結(jié)(可編輯)
- 2024年xx村兩委涉案資金退還保證書
- 2024年憲法宣傳周活動(dòng)總結(jié)+在機(jī)關(guān)“弘揚(yáng)憲法精神推動(dòng)發(fā)改工作高質(zhì)量發(fā)展”專題宣講報(bào)告會(huì)上的講話
- 2024年XX村合作社年報(bào)總結(jié)
- 2024-2025年秋季第一學(xué)期初中歷史上冊(cè)教研組工作總結(jié)
- 2024年小學(xué)高級(jí)教師年終工作總結(jié)匯報(bào)
- 2024-2025年秋季第一學(xué)期初中物理上冊(cè)教研組工作總結(jié)
- 2024年xx鎮(zhèn)交通年度總結(jié)
- 2024-2025年秋季第一學(xué)期小學(xué)語(yǔ)文教師工作總結(jié)
- 2024年XX村陳規(guī)陋習(xí)整治報(bào)告
- 2025年學(xué)校元旦迎新盛典活動(dòng)策劃方案
- 2024年學(xué)校周邊安全隱患自查報(bào)告
- 2024年XX鎮(zhèn)農(nóng)村規(guī)劃管控述職報(bào)告