1. 程式人生 > >linux資料包接收過程

linux資料包接收過程

最近發現瞭解linux內資料包的傳輸機制很有必要,首先總結一下接收過程。資料包從hostA向hostB發包,如下圖所示:


一. linux中包的傳輸過程

(1).      驅動載入並初始化

(2).      資料包到達網絡卡(網絡卡中的緩衝區或佇列)

(3).      包通過DMA拷貝到核心記憶體中的環形緩衝區中(環形緩衝區中的記憶體區域是驅動進行分配和對映的,分配後驅動會將記憶體地址和大小告訴網絡卡NIC;若沒有分配好的記憶體,包可能會丟失;傳輸前要通過CRC檢查包是否有效;若網絡卡支援硬體層多佇列,此時每個佇列會對應一個單獨的記憶體區域,多個CPU可以處理這些資料;若支援packet steering,資料也會多個CPU)。現在大多數的網絡卡都會使用DMA來傳輸資料包

(4).      產生硬中斷來讓系統知道一個包已經在記憶體中了

(5).      驅動通過Ksoftirqd程序通過呼叫NAPI poll函式將包從環形緩衝區中取出(函式用於監控多個事件,在一個迴圈中)。Ksoftirqd程序執行在系統中的每個CPU中,它們在boot時就被註冊了。NAPI poll函式在裝置驅動初始化時被註冊

(6).      將資料傳輸到網路層(IP層),資料格式為skb,便於繼續進行處理;網路層檢查包是否有效,然後檢查乙太網報頭,刪除乙太網報頭並將包傳送到IP層

(7).      IP層通過檢查IP頭校驗,檢查包是否有效。判斷是否需要IP route。刪除IP頭部,將包傳送到TCP 層

(8).      TCP層會檢查包是否有效。搜尋與包連線的TCP控制塊,搜尋到連線後,它用該協議來處理包。如果它收到新的資料,則將資料拷貝或傳送到receive socketbuffer

(9).      資料被協議層送到接收緩衝區,socket可以到達

資料包從底層傳到上層的過程中,會逐漸拆包,如下圖所示:


二. RQ和Softirq

這裡還要解釋一下IRQ和Softirq

1. IRQ

當一個數據幀通過DMA被寫到RAM,網絡卡怎樣通知系統資料已經準備好被處理了呢?傳統方法中,一個網絡卡會產生一箇中斷請求(IRQ),代表資料已經到達了。IRQ有三種類型:MSI-X,MSI以及合法IRQ。如果需要傳輸的資料量很大,將會導致有大量的IRQ產生。產生越多的IRQ,其他任務可分配到越少的CPU時間,因此會佔據大量的CPU時間。

         NAPI能夠減少IRQ的數量,NAPI讓裝置驅動在驅動初始化時註冊一個poll函式,這個函式能夠被NAPI呼叫。網路裝置驅動中NAPI的使用是這樣的:

(1).      NAPI在初始的時候是off狀態,驅動enable它。

(2).      一個數據包到達,網絡卡通過DMA將其傳輸到記憶體中

(3).      一個IRQ由網絡卡產生,IRQ handler由驅動產生

(4).      驅動會通過softirq(軟中斷請求)喚醒NAPI子系統。此時會在一個單獨的執行執行緒中呼叫驅動註冊poll函式收包。

(5).      驅動通過NAPI disable後面的IRQ,這通過NAPI子系統來處理包,無須裝置中斷。

(6).      一旦完成工作,NAPI子系統被disable,IRQ被重新enable

(7).     回到步驟2重新執行

2. Softirq

Linux核心中的Softirq系統是一個機制,能夠執行中斷handler上下文外的程式。Softirq在驅動中實現。Softirq很重要,硬體中斷可能會在中斷handler的一部分或全部的過程中被disable。中斷disable時間越長,越可能錯過一些重要事件。Softirq能夠儘可能減少在irq handler裡做的事情,使irq handler儘快返回。把大部分可以延遲做得事情放在softirq裡做。從而儘快完成任務和enable中斷。Softirq系統可以被想象為一系列核心執行緒(每個CPU一個softirq),能夠執行不同softirq事件註冊的handler函式。

參考文獻:

[1] https://blog.packagecloud.io/eng/2016/06/22/monitoring-tuning-linux-networking-stack-receiving-data/#ip-protocol-layer

[2] http://www.cubrid.org/blog/dev-platform/understanding-tcp-ip-network-stack/

[3] http://www.cnblogs.com/sammyliu/p/5225623.html