Linux內核源代碼:tcp/ip協議棧的調用
6 數據鏈路層流程
6.1 發(fā)送端
功能上,在物理層提供比特流服務的基礎上,建立相鄰結點之間的數據鏈路,通過差錯控制提供數據幀(Frame)在信道上無差錯的傳輸,并進行各電路上的動作系列。
數據鏈路層在不可靠的物理介質上提供可靠的傳輸。
該層的作用包括:物理地址尋址、數據的成幀、流量控制、數據的檢錯、重發(fā)等。在這一層,數據的單位稱為幀(frame)。數據鏈路層協議的代表包括:SDLC、HDLC、PPP、STP、幀中繼等。
實現上,Linux 提供了一個 Network device 的抽象層,其實現在 linux/net/core/dev.c。具體的物理網絡設備在設備驅動中(driver.c)需要實現其中的虛函數。Network Device 抽象層調用具體網絡設備的函數。
發(fā)送端調用dev_queue_xmit,這個函數實際上調用__dev_queue_xmit:
發(fā)現它調用了dev_hard_start_xmit函數:
調用xmit_one:
調用trace_net_dev_start_xmit,實際上調用__net_dev_start_xmit函數:
到此,調用鏈結束。gdb調試如下:
6.2 接收端
簡要過程:
一個 package 到達機器的物理網絡適配器,當它接收到數據幀時,就會觸發(fā)一個中斷,并將通過 DMA 傳送到位于 linux kernel 內存中的 rx_ring。
網卡發(fā)出中斷,通知 CPU 有個 package 需要它處理。中斷處理程序主要進行以下一些操作,包括分配 skb_buff 數據結構,并將接收到的數據幀從網絡適配器I/O端口拷貝到skb_buff 緩沖區(qū)中;
從數據幀中提取出一些信息,并設置 skb_buff 相應的參數,這些參數將被上層的網絡協議使用,例如skb->protocol;
終端處理程序經過簡單處理后,發(fā)出一個軟中斷(NET_RX_SOFTIRQ),通知內核接收到新的數據幀。
內核 2.5 中引入一組新的 API 來處理接收的數據幀,即 NAPI。所以,驅動有兩種方式通知內核:(1) 通過以前的函數netif_rx;(2)通過NAPI機制。該中斷處理程序調用 Network device的 netif_rx_schedule 函數,進入軟中斷處理流程,再調用 net_rx_action 函數。
該函數關閉中斷,獲取每個 Network device 的 rx_ring 中的所有 package,最終 pacakage 從 rx_ring 中被刪除,進入 netif _receive_skb 處理流程。
netif_receive_skb 是鏈路層接收數據報的最后一站。它根據注冊在全局數組 ptype_all 和 ptype_base 里的網絡層數據報類型,把數據報遞交給不同的網絡層協議的接收函數(INET域中主要是ip_rcv和arp_rcv)。該函數主要就是調用第三層協議的接收函數處理該skb包,進入第三層網絡層處理。
入口函數是net_rx_action:
發(fā)現調用napi_poll,實質上調用napi_gro_receive函數:
napi_gro_receive 會直接調用 netif_receive_skb_core。而它會調用__netif_receive_skb_one_core,將數據包交給上層 ip_rcv 進行處理。
調用結束之后,通過軟中斷通知CPU,至此,調用鏈結束。gdb驗證如下:
7 物理層流程
7.1 發(fā)送端
物理層在收到發(fā)送請求之后,通過 DMA 將該主存中的數據拷貝至內部RAM(buffer)之中。在數據拷貝中,同時加入符合以太網協議的相關header,IFG、前導符和CRC。對于以太網網絡,物理層發(fā)送采用CSMA/CD,即在發(fā)送過程中偵聽鏈路沖突。
一旦網卡完成報文發(fā)送,將產生中斷通知CPU,然后驅動層中的中斷處理程序就可以刪除保存的 skb 了。
7.2 接收端
一個 package 到達機器的物理網絡適配器,當它接收到數據幀時,就會觸發(fā)一個中斷,并將通過 DMA 傳送到位于 linux kernel 內存中的 rx_ring。
網卡發(fā)出中斷,通知 CPU 有個 package 需要它處理。中斷處理程序主要進行以下一些操作,包括分配 skb_buff 數據結構,并將接收到的數據幀從網絡適配器I/O端口拷貝到skb_buff 緩沖區(qū)中;從數據幀中提取出一些信息,并設置 skb_buff 相應的參數,這些參數將被上層的網絡協議使用,例如skb->protocol;
終端處理程序經過簡單處理后,發(fā)出一個軟中斷(NET_RX_SOFTIRQ),通知內核接收到新的數據幀。
內核 2.5 中引入一組新的 API 來處理接收的數據幀,即 NAPI。所以,驅動有兩種方式通知內核:(1) 通過以前的函數netif_rx;(2)通過NAPI機制。該中斷處理程序調用 Network device的 netif_rx_schedule 函數,進入軟中斷處理流程,再調用 net_rx_action 函數。
該函數關閉中斷,獲取每個 Network device 的 rx_ring 中的所有 package,最終 pacakage 從 rx_ring 中被刪除,進入 netif _receive_skb 處理流程。
netif_receive_skb 是鏈路層接收數據報的最后一站。它根據注冊在全局數組 ptype_all 和 ptype_base 里的網絡層數據報類型,把數據報遞交給不同的網絡層協議的接收函數(INET域中主要是ip_rcv和arp_rcv)。該函數主要就是調用第三層協議的接收函數處理該skb包,進入第三層網絡層處理。
8 時序圖展示和總結
時序圖如下:
本次實驗主要是通過分析Linux內核源代碼,一步步地通過gdb進行調試函數調用鏈,最終清楚了tcp/ip協議棧的調用過程。因為時間有限,部分細節(jié)可能會有錯誤,希望讀者多加指正。

請輸入評論內容...
請輸入評論/評論長度6~500個字
最新活動更多
-
即日-9.16點擊進入 >> 【限時福利】TE 2025國際物聯網展·深圳站
-
10月23日立即報名>> Works With 開發(fā)者大會深圳站
-
10月24日立即參評>> 【評選】維科杯·OFweek 2025(第十屆)物聯網行業(yè)年度評選
-
11月27日立即報名>> 【工程師系列】汽車電子技術在線大會
-
12月18日立即報名>> 【線下會議】OFweek 2025(第十屆)物聯網產業(yè)大會
-
精彩回顧立即查看>> 【限時下載】ADI中國三十周年感恩回饋助力企業(yè)升級!