Linux 服務器收到網絡數據包,需要經過哪些處理,一步步將數據傳給應用進程的呢?應用進程發(fā)送數據包時,Linux 又是如何操作將數據包發(fā)送出去的呢?今天我們就來聊聊這個話題。
在準備好接收網絡數據包之前,Linux需要做很多準備工作,例如:網絡子系統(tǒng)的初始化、協(xié)議棧的注冊、網卡驅動的初始化、啟動網卡等等,只有這些都準備好了之后,才能真正開始接收網絡包。
網絡協(xié)議棧
在介紹Linux收發(fā)網絡數據包之前,我們先來了解一下Linux網絡協(xié)議棧。
國際標準化組織制定了開放式系統(tǒng)互聯(lián)通信參考模型(Open System Interconnection Reference Model),也就是 OSI 網絡模型,該模型主要有 7 層,分別是應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層以及物理層。
由于 OSI 模型太復雜,提出的只是存在于概念和理論上的一種模型,分層太多,增加了網絡工作的復雜性,所以沒有大規(guī)模應用。 我們比較常見是TCP/IP 網絡模型,Linux 系統(tǒng)正是按照這套網絡模型來實現(xiàn)網絡協(xié)議棧的。
TCP/IP 網絡模型共有 4 層,分別是應用層、傳輸層、網絡層和網絡接口層,每一層負責的職能如下:
1、應用層 對應于OSI參考模型的高層,為用戶提供所需要的各種服務,例如:FTP、Telnet、DNS、SMTP等.
2、傳輸層 對應于OSI參考模型的傳輸層,為應用層實體提供端到端的通信功能,保證了數據包的順序傳送及數據的完整性。該層定義了兩個主要的協(xié)議:傳輸控制協(xié)議(TCP)和用戶數據報協(xié)議(UDP).
3、網絡層 對應于OSI參考模型的網絡層,主要解決主機到主機的通信問題。它所包含的協(xié)議設計數據包在整個網絡上的邏輯傳輸。注重重新賦予主機一個IP地址來完成對主機的尋址,它還負責數據包在多種網絡中的路由。該層有三個主要協(xié)議:網際協(xié)議(IP)、互聯(lián)網組管理協(xié)議(IGMP)和互聯(lián)網控制報文協(xié)議(ICMP)。
4、網絡接口層 與OSI參考模型中的物理層和數據鏈路層相對應。它負責監(jiān)視數據在主機和網絡之間的交換。事實上,TCP/IP本身并未定義該層的協(xié)議,而由參與互連的各網絡使用自己的物理層和數據鏈路層協(xié)議,然后與TCP/IP的網絡接入層進行連接。地址解析協(xié)議(ARP)工作在此層,即OSI參考模型的數據鏈路層。
接收網絡數據包
網絡數據包到達網卡后,按照FIFO順序被存入網卡的接收隊列,網卡通過 DMA 技術,將網絡包寫入到指定的內存地址(Ring Buffer)。
Ring Buffer是在網卡驅動程序啟動時創(chuàng)建和初始化的,存儲的是sk_buff緩沖區(qū)的描述符(物理地址和大小等)。
當網絡包到達時,從Ring Buffer獲取指向的sk_buff描述符,通過DMA將數據寫入該地址。等sk_buff中的數據交由上層協(xié)議棧處理后,Ring Buffer中的描述更新為新分配的sk_buff。
接著網卡向 CPU 發(fā)起硬件中斷,當 CPU 收到硬件中斷請求后,根據中斷注冊表,找到注冊的中斷處理函數。
硬件中斷處理函數會做如下的事情:
1、屏蔽網卡的中斷
目的是避免CPU被頻繁中斷而無法處理其他任務,屏蔽中斷是告訴網卡已經知道內存中有數據了,下次再收到數據包直接寫內存就可以了,不要再通知 CPU 了。
2、發(fā)起軟中斷,恢復剛才屏蔽的中斷
內核中的 ksoftirqd 線程收到軟中斷后,就會調用相應軟中斷的處理函數來輪詢處理數據,即:從Ring Buffer 中獲取一個數據幀,用 sk_buff 表示,作為一個網絡包交給網絡協(xié)議棧從下到上進行逐層處理。
網絡協(xié)議棧對網絡包的處理流程如下:
1、網絡接口層
首先,網絡接口層檢查報文的合法性和正確性,如果不合法或報文校驗不正確則丟棄,否則找出上層協(xié)議的類型(IPv4還是IPv6),去掉幀頭、幀尾,然后交給上層即網絡層處理。
2、網絡層
網絡層取出IP頭,判斷網絡包下一步的走向,是轉發(fā)還是交給上層。當確認網絡包是要發(fā)送給本機后,就取出上層協(xié)議的類型(比如TCP或UDP),去掉IP頭,然后交給傳輸層處理。
3、傳輸層
傳輸層取出 TCP 頭或者 UDP 頭后,根據四元組【 源 IP、源端口、目的 IP、目的端口 】,找出對應的 Socket,并把數據拷貝到 Socket 的接收緩沖區(qū)。
4、應用層
最后,應用層程序調用 Socket 接口,將內核的 Socket 接收緩沖區(qū)的數據拷貝到應用層的緩沖區(qū)。
到這里,一個網絡包的接收過程就結束了。
發(fā)送網絡數據包
我們了解了網絡包的接收流程后,就很容易理解網絡包的發(fā)送流程了。網絡包的發(fā)送方向,正好跟接收方向相反。
首先,應用程序調用 Socket 發(fā)送網絡包的接口。這是一個系統(tǒng)調用,會從用戶態(tài)陷入到內核態(tài)的套接字層中。
套接字層會申請一個內核態(tài)的 sk_buff 內存,將用戶待發(fā)送的數據拷貝到 sk_buff 內存,并將其加入到Socket發(fā)送緩沖區(qū)等待網絡協(xié)議棧的處理。
由于網絡數據包從應用程序傳到內核時是原始數據,協(xié)議棧要在原始數據中加入通信約定才能保證數據到達服務端能被正確識別。網絡協(xié)議棧從 Socket 發(fā)送緩沖區(qū)中,取出數據包,然后按照 TCP/IP 棧的分層(傳輸層、網絡層、網絡接口層),從上到下逐層進行處理,各層將協(xié)議的頭信息不斷插入到數據包中。
協(xié)議棧對發(fā)送數據包的處理流程如下:
1、傳輸層
在傳輸層,會為器添加TCP頭,同時拷貝一個新的 sk_buff 副本,這是因為 sk_buff 在到達網卡發(fā)送完成的時候,會被釋放掉,而TCP 協(xié)議是支持重傳的,為確保網絡包可靠傳輸,在收到對方的 ACK 之前,這個 sk_buff 不能被刪除。
2、網絡層
在網絡層,主要會做這些工作:選取路由(確認下一跳的 IP)、填充 IP 頭、netfilter 過濾、對超過 MTU 大小的數據包進行分片。處理完這些工作后會交給網絡接口層處理。
3、網絡接口層
網絡接口層會進行物理地址尋址,以找到下一跳的 MAC 地址,填充幀頭和幀尾,將其放到發(fā)送隊列中。然后觸發(fā)軟中斷告訴網卡驅動程序:隊列中有新的網絡包需要發(fā)送。驅動程序收到通知會通過 DMA ,從發(fā)送包隊列中讀出網絡幀,并通過DMA將數據寫入網卡的FIFO發(fā)送隊列。
4、網卡設備
網卡設備從FIFO發(fā)送隊列中取出數據包,將其發(fā)送到網絡;當發(fā)送完成的時候,網卡設備會觸發(fā)一個硬中斷來釋放內存,主要是釋放 sk_buff內存和清理 RingBuffer 內存。最后,當收到這個 TCP 報文的 ACK 應答時,傳輸層就會釋放原始的 sk_buff。
至此,一個網絡包的發(fā)送流程就結束了。
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11304瀏覽量
209498 -
Linux系統(tǒng)
+關注
關注
4文章
593瀏覽量
27397 -
TCP
+關注
關注
8文章
1353瀏覽量
79074 -
數據包
+關注
關注
0文章
261瀏覽量
24394 -
網絡層
+關注
關注
0文章
40瀏覽量
10297
原文標題:簡述Linux系統(tǒng)收發(fā)網絡數據包的過程
文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論