網絡數據是如何傳遞給進程的

 戳藍字「TopCoder」關注我們哦!

在分析網卡數據是如何傳遞給進程的流程之前,要知道數據是如何從進程寫到網卡的,因爲只有發起方寫數據到網卡然後接收方纔能接收到並處理。

發送數據

發送方的發送數據的處理流程大致爲:用戶空間 -> 內核 -> 網卡 -> 網絡。

在用戶態空間,調用發送數據接口 send/sento/wirte 等寫數據包,在內核空間會根據不同的協議走不同的流程。以TCP爲例,TCP是一種流協議,內核只是將數據包追加到套接字的發送隊列中,真正發送數據的時刻,則是由TCP協議來控制的。TCP協議處理完成之後會交給IP協議繼續處理,最後會調用網卡的發送函數,將數據包發送到網卡。

接收數據

接收方的接收數據的處理流程大致爲:網絡 -> 網卡 -> 內核(epoll等) -> 進程(業務處理邏輯)。

網絡中數據首先到達網卡,對於網卡來說,數據包的到達是一個無法預料的事件,系統需要通過某種手段來得知該事件。一般來說,有2種方案:輪詢和通知,輪詢機制就是不斷輪詢網卡看數據有沒有到來,該方式無疑會浪費較多的CPU資源,沒數據時會造成大量的空輪詢。通知機制就是網卡接收到數據時再通知CPU,然後再讀取數據即可。

網卡的數據通知機制看起來很完美了,但是實際應用中,CPU響應中斷處理時,爲了不影響當前的工作,需要將當前工作的上下文保存起來,然後再進行中斷處理。試想,當前千兆、萬兆網卡已經非常普遍,若是那時網卡滿負載,那麼每秒鐘就會產生大量的中斷。除了切換過程帶來的計算代價,上下文的切換還會導致CPU Cache的失效,對於高性能服務器來說,這是一個不容忽視的問題。因此,Linux做了優化,組合了通知和輪詢的機制,簡單來說,在CPU響應網卡中斷時,不再僅僅是處理一個數據包就退出,而是使用輪詢的方式繼續嘗試處理新數據包,直到沒有新數據包到來,或者達到設置的一次中斷最多處理的數據包個數。

注意網卡的硬中斷處理是在網卡驅動中進行的,硬中斷處理是一個特殊的上下文,CPU會屏蔽掉絕大部分中斷,並且有不少的限制。所以硬中斷應儘可能快地處理,以提高系統的響應速度,因此內核將具體的處理工作放到了軟中斷中。

數據離開網卡驅動之後就進入到了協議棧,經過IP層、網絡層協議的處理,就會觸發IO讀事件,比如epoll的reactor模型中,就會觸發對應的讀事件,然後回調對應的IO處理函數,數據之後會交給業務線程來處理,比如Netty的數據接收處理流程就是這樣的。

 推薦閱讀 


歡迎小夥伴關注【TopCoder】閱讀更多精彩好文。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章