www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 單片機 > 小林coding
[導讀]為了使得多種設備能通過網(wǎng)絡相互通信,和為了解決各種不同設備在網(wǎng)絡互聯(lián)中的兼容性問題。

大家好,我是小林。

之前寫過一篇:你不好奇 Linux 是如何收發(fā)網(wǎng)絡包的? 文章。

當時有些地方寫的比較籠統(tǒng),然后我「把 Linux 接收+發(fā)送網(wǎng)絡包的流程」這部分內(nèi)容完善了下,現(xiàn)在重新分享給大家。

發(fā)車發(fā)車!

網(wǎng)絡模型

為了使得多種設備能通過網(wǎng)絡相互通信,和為了解決各種不同設備在網(wǎng)絡互聯(lián)中的兼容性問題。

國際標準化組織制定了開放式系統(tǒng)互聯(lián)通信參考模型(Open System Interconnection Reference Model),也就是 OSI 網(wǎng)絡模型。

該模型主要有 7 層,分別是應用層、表示層、會話層、傳輸層、網(wǎng)絡層、數(shù)據(jù)鏈路層以及物理層。

每一層負責的職能都不同,如下:

  • 應用層,負責給應用程序提供統(tǒng)一的接口;
  • 表示層,負責把數(shù)據(jù)轉換成兼容另一個系統(tǒng)能識別的格式;
  • 會話層,負責建立、管理和終止表示層實體之間的通信會話;
  • 傳輸層,負責端到端的數(shù)據(jù)傳輸;
  • 網(wǎng)絡層,負責數(shù)據(jù)的路由、轉發(fā)、分片;
  • 數(shù)據(jù)鏈路層,負責數(shù)據(jù)的封幀和差錯檢測,以及 MAC 尋址;
  • 物理層,負責在物理網(wǎng)絡中傳輸數(shù)據(jù)幀;

由于 OSI 模型實在太復雜,提出的也只是概念理論上的分層,并沒有提供具體的實現(xiàn)方案。

事實上,我們比較常見,也比較實用的是四層模型,即 TCP/IP 網(wǎng)絡模型,Linux 系統(tǒng)正是按照這套網(wǎng)絡模型來實現(xiàn)網(wǎng)絡協(xié)議棧的。

TCP/IP 網(wǎng)絡模型共有 4 層,分別是應用層、傳輸層、網(wǎng)絡層和網(wǎng)絡接口層,每一層負責的職能如下:

  • 應用層,負責向用戶提供一組應用程序,比如 HTTP、DNS、FTP 等;
  • 傳輸層,負責端到端的通信,比如 TCP、UDP 等;
  • 網(wǎng)絡層,負責網(wǎng)絡包的封裝、分片、路由、轉發(fā),比如 IP、ICMP 等;
  • 網(wǎng)絡接口層,負責網(wǎng)絡包在物理網(wǎng)絡中的傳輸,比如網(wǎng)絡包的封幀、 MAC 尋址、差錯檢測,以及通過網(wǎng)卡傳輸網(wǎng)絡幀等;

TCP/IP 網(wǎng)絡模型相比 OSI 網(wǎng)絡模型簡化了不少,也更加易記,它們之間的關系如下圖:

不過,我們常說的七層和四層負載均衡,是用 OSI 網(wǎng)絡模型來描述的,七層對應的是應用層,四層對應的是傳輸層。


Linux 網(wǎng)絡協(xié)議棧

我們可以把自己的身體比作應用層中的數(shù)據(jù),打底衣服比作傳輸層中的 TCP 頭,外套比作網(wǎng)絡層中 IP 頭,帽子和鞋子分別比作網(wǎng)絡接口層的幀頭和幀尾。

在冬天這個季節(jié),當我們要從家里出去玩的時候,自然要先穿個打底衣服,再套上保暖外套,最后穿上帽子和鞋子才出門,這個過程就好像我們把 TCP 協(xié)議通信的網(wǎng)絡包發(fā)出去的時候,會把應用層的數(shù)據(jù)按照網(wǎng)絡協(xié)議棧層層封裝和處理。

你從下面這張圖可以看到,應用層數(shù)據(jù)在每一層的封裝格式。

其中:

  • 傳輸層,給應用數(shù)據(jù)前面增加了 TCP  頭;
  • 網(wǎng)絡層,給 TCP 數(shù)據(jù)包前面增加了 IP  頭;
  • 網(wǎng)絡接口層,給 IP 數(shù)據(jù)包前后分別增加了幀頭和幀尾;

這些新增的頭部和尾部,都有各自的作用,也都是按照特定的協(xié)議格式填充,這每一層都增加了各自的協(xié)議頭,那自然網(wǎng)絡包的大小就增大了,但物理鏈路并不能傳輸任意大小的數(shù)據(jù)包,所以在以太網(wǎng)中,規(guī)定了最大傳輸單元(MTU)是1500字節(jié),也就是規(guī)定了單次傳輸?shù)淖畲?IP 包大小。

當網(wǎng)絡包超過 MTU 的大小,就會在網(wǎng)絡層分片,以確保分片后的 IP 包不會超過 MTU 大小,如果 MTU 越小,需要的分包就越多,那么網(wǎng)絡吞吐能力就越差,相反的,如果 MTU 越大,需要的分包就越少,那么網(wǎng)絡吞吐能力就越好。

知道了 TCP/IP 網(wǎng)絡模型,以及網(wǎng)絡包的封裝原理后,那么 Linux 網(wǎng)絡協(xié)議棧的樣子,你想必猜到了大概,它其實就類似于 TCP/IP 的四層結構:

從上圖的的網(wǎng)絡協(xié)議棧,你可以看到:

  • 應用程序需要通過系統(tǒng)調(diào)用,來跟 Socket 層進行數(shù)據(jù)交互;
  • Socket 層的下面就是傳輸層、網(wǎng)絡層和網(wǎng)絡接口層;
  • 最下面的一層,則是網(wǎng)卡驅動程序和硬件網(wǎng)卡設備;

Linux 接收網(wǎng)絡包的流程

網(wǎng)卡是計算機里的一個硬件,專門負責接收和發(fā)送網(wǎng)絡包,當網(wǎng)卡接收到一個網(wǎng)絡包后,會通過 DMA 技術,將網(wǎng)絡包寫入到指定的內(nèi)存地址,也就是寫入到 Ring Buffer ,這個是一個環(huán)形緩沖區(qū),接著就會告訴操作系統(tǒng)這個網(wǎng)絡包已經(jīng)到達。

那應該怎么告訴操作系統(tǒng)這個網(wǎng)絡包已經(jīng)到達了呢?

最簡單的一種方式就是觸發(fā)中斷,也就是每當網(wǎng)卡收到一個網(wǎng)絡包,就觸發(fā)一個中斷告訴操作系統(tǒng)。

但是,這存在一個問題,在高性能網(wǎng)絡場景下,網(wǎng)絡包的數(shù)量會非常多,那么就會觸發(fā)非常多的中斷,要知道當 CPU  收到了中斷,就會停下手里的事情,而去處理這些網(wǎng)絡包,處理完畢后,才會回去繼續(xù)其他事情,那么頻繁地觸發(fā)中斷,則會導致 CPU 一直沒完沒了的處理中斷,而導致其他任務可能無法繼續(xù)前進,從而影響系統(tǒng)的整體效率。

所以為了解決頻繁中斷帶來的性能開銷,Linux 內(nèi)核在 2.6 版本中引入了 NAPI 機制,它是混合「中斷和輪詢」的方式來接收網(wǎng)絡包,它的核心概念就是不采用中斷的方式讀取數(shù)據(jù),而是首先采用中斷喚醒數(shù)據(jù)接收的服務程序,然后poll的方法來輪詢數(shù)據(jù)。

因此,當有網(wǎng)絡包到達時,會通過 DMA 技術,將網(wǎng)絡包寫入到指定的內(nèi)存地址,接著網(wǎng)卡向 CPU 發(fā)起硬件中斷,當 CPU 收到硬件中斷請求后,根據(jù)中斷表,調(diào)用已經(jīng)注冊的中斷處理函數(shù)。

硬件中斷處理函數(shù)會做如下的事情:

  • 需要先「暫時屏蔽中斷」,表示已經(jīng)知道內(nèi)存中有數(shù)據(jù)了,告訴網(wǎng)卡下次再收到數(shù)據(jù)包直接寫內(nèi)存就可以了,不要再通知 CPU 了,這樣可以提高效率,避免 CPU 不停的被中斷。
  • 接著,發(fā)起「軟中斷」,然后恢復剛才屏蔽的中斷。

至此,硬件中斷處理函數(shù)的工作就已經(jīng)完成。

硬件中斷處理函數(shù)做的事情很少,主要耗時的工作都交給軟中斷處理函數(shù)了。

軟中斷的處理

內(nèi)核中的 ksoftirqd 線程專門負責軟中斷的處理,當 ksoftirqd 內(nèi)核線程收到軟中斷后,就會來輪詢處理數(shù)據(jù)。

ksoftirqd 線程會從 Ring Buffer 中獲取一個數(shù)據(jù)幀,用 sk_buff 表示,從而可以作為一個網(wǎng)絡包交給網(wǎng)絡協(xié)議棧進行逐層處理。

網(wǎng)絡協(xié)議棧

首先,會先進入到網(wǎng)絡接口層,在這一層會檢查報文的合法性,如果不合法則丟棄,合法則會找出該網(wǎng)絡包的上層協(xié)議的類型,比如是 IPv4,還是 IPv6,接著再去掉幀頭和幀尾,然后交給網(wǎng)絡層。

到了網(wǎng)絡層,則取出 IP 包,判斷網(wǎng)絡包下一步的走向,比如是交給上層處理還是轉發(fā)出去。當確認這個網(wǎng)絡包要發(fā)送給本機后,就會從 IP 頭里看看上一層協(xié)議的類型是 TCP 還是 UDP,接著去掉 IP 頭,然后交給傳輸層。

傳輸層取出 TCP 頭或 UDP 頭,根據(jù)四元組「源 IP、源端口、目的 IP、目的端口」 作為標識,找出對應的 Socket,并把數(shù)據(jù)放到 Socket 的接收緩沖區(qū)。

最后,應用層程序調(diào)用 Socket 接口,將內(nèi)核的 Socket 接收緩沖區(qū)的數(shù)據(jù)「拷貝」到應用層的緩沖區(qū),然后喚醒用戶進程。

至此,一個網(wǎng)絡包的接收過程就已經(jīng)結束了,你也可以從下圖左邊部分看到網(wǎng)絡包接收的流程,右邊部分剛好反過來,它是網(wǎng)絡包發(fā)送的流程。

Linux 發(fā)送網(wǎng)絡包的流程

如上圖的右半部分,發(fā)送網(wǎng)絡包的流程正好和接收流程相反。

首先,應用程序會調(diào)用 Socket 發(fā)送數(shù)據(jù)包的接口,由于這個是系統(tǒng)調(diào)用,所以會從用戶態(tài)陷入到內(nèi)核態(tài)中的 Socket 層,內(nèi)核會申請一個內(nèi)核態(tài)的 sk_buff 內(nèi)存,將用戶待發(fā)送的數(shù)據(jù)拷貝到 sk_buff 內(nèi)存,并將其加入到發(fā)送緩沖區(qū)。

接下來,網(wǎng)絡協(xié)議棧從 Socket 發(fā)送緩沖區(qū)中取出 sk_buff,并按照 TCP/IP 協(xié)議棧從上到下逐層處理。

如果使用的是 TCP 傳輸協(xié)議發(fā)送數(shù)據(jù),那么先拷貝一個新的 sk_buff 副本 ,這是因為 sk_buff 后續(xù)在調(diào)用網(wǎng)絡層,最后到達網(wǎng)卡發(fā)送完成的時候,這個 sk_buff 會被釋放掉。而 TCP 協(xié)議是支持丟失重傳的,在收到對方的 ACK 之前,這個 sk_buff 不能被刪除。所以內(nèi)核的做法就是每次調(diào)用網(wǎng)卡發(fā)送的時候,實際上傳遞出去的是 sk_buff 的一個拷貝,等收到 ACK 再真正刪除。

接著,對 sk_buff 填充 TCP 頭。這里提一下,sk_buff 可以表示各個層的數(shù)據(jù)包,在應用層數(shù)據(jù)包叫 data,在 TCP 層我們稱為 segment,在 IP 層我們叫 packet,在數(shù)據(jù)鏈路層稱為 frame。

你可能會好奇,為什么全部數(shù)據(jù)包只用一個結構體來描述呢?協(xié)議棧采用的是分層結構,上層向下層傳遞數(shù)據(jù)時需要增加包頭,下層向上層數(shù)據(jù)時又需要去掉包頭,如果每一層都用一個結構體,那在層之間傳遞數(shù)據(jù)的時候,就要發(fā)生多次拷貝,這將大大降低 CPU 效率。

于是,為了在層級之間傳遞數(shù)據(jù)時,不發(fā)生拷貝,只用 sk_buff 一個結構體來描述所有的網(wǎng)絡包,那它是如何做到的呢?是通過調(diào)整 sk_buff 中data的指針,比如:

  • 當接收報文時,從網(wǎng)卡驅動開始,通過協(xié)議棧層層往上傳送數(shù)據(jù)報,通過增加 skb->data 的值,來逐步剝離協(xié)議首部。
  • 當要發(fā)送報文時,創(chuàng)建 sk_buff 結構體,數(shù)據(jù)緩存區(qū)的頭部預留足夠的空間,用來填充各層首部,在經(jīng)過各下層協(xié)議時,通過減少 skb->data 的值來增加協(xié)議首部。

你可以從下面這張圖看到,當發(fā)送報文時,data 指針的移動過程。

至此,傳輸層的工作也就都完成了。

然后交給網(wǎng)絡層,在網(wǎng)絡層里會做這些工作:選取路由(確認下一跳的 IP)、填充 IP 頭、netfilter 過濾、對超過 MTU 大小的數(shù)據(jù)包進行分片。處理完這些工作后會交給網(wǎng)絡接口層處理。

網(wǎng)絡接口層會通過 ARP 協(xié)議獲得下一跳的 MAC 地址,然后對 sk_buff 填充幀頭和幀尾,接著將 sk_buff 放到網(wǎng)卡的發(fā)送隊列中。

這一些工作準備好后,會觸發(fā)「軟中斷」告訴網(wǎng)卡驅動程序,這里有新的網(wǎng)絡包需要發(fā)送,驅動程序會從發(fā)送隊列中讀取 sk_buff,將這個 sk_buff 掛到 RingBuffer 中,接著將 sk_buff 數(shù)據(jù)映射到網(wǎng)卡可訪問的內(nèi)存 DMA 區(qū)域,最后觸發(fā)真實的發(fā)送。

當數(shù)據(jù)發(fā)送完成以后,其實工作并沒有結束,因為內(nèi)存還沒有清理。當發(fā)送完成的時候,網(wǎng)卡設備會觸發(fā)一個硬中斷來釋放內(nèi)存,主要是釋放 sk_buff 內(nèi)存和清理  RingBuffer 內(nèi)存。

最后,當收到這個 TCP 報文的 ACK 應答時,傳輸層就會釋放原始的 sk_buff 。

發(fā)送網(wǎng)絡數(shù)據(jù)的時候,涉及幾次內(nèi)存拷貝操作?

第一次,調(diào)用發(fā)送數(shù)據(jù)的系統(tǒng)調(diào)用的時候,內(nèi)核會申請一個內(nèi)核態(tài)的 sk_buff 內(nèi)存,將用戶待發(fā)送的數(shù)據(jù)拷貝到 sk_buff 內(nèi)存,并將其加入到發(fā)送緩沖區(qū)。

第二次,在使用 TCP 傳輸協(xié)議的情況下,從傳輸層進入網(wǎng)絡層的時候,每一個 sk_buff 都會被克隆一個新的副本出來。副本 sk_buff 會被送往網(wǎng)絡層,等它發(fā)送完的時候就會釋放掉,然后原始的 sk_buff 還保留在傳輸層,目的是為了實現(xiàn) TCP 的可靠傳輸,等收到這個數(shù)據(jù)包的 ACK 時,才會釋放原始的 sk_buff 。

第三次,當 IP 層發(fā)現(xiàn) sk_buff 大于 MTU 時才需要進行。會再申請額外的 sk_buff,并將原來的 sk_buff 拷貝為多個小的 sk_buff。

總結

電腦與電腦之間通常都是通過話網(wǎng)卡、交換機、路由器等網(wǎng)絡設備連接到一起,那由于網(wǎng)絡設備的異構性,國際標準化組織定義了一個七層的 OSI 網(wǎng)絡模型,但是這個模型由于比較復雜,實際應用中并沒有采用,而是采用了更為簡化的 TCP/IP 模型,Linux 網(wǎng)絡協(xié)議棧就是按照了該模型來實現(xiàn)的。

TCP/IP 模型主要分為應用層、傳輸層、網(wǎng)絡層、網(wǎng)絡接口層四層,每一層負責的職責都不同,這也是 Linux 網(wǎng)絡協(xié)議棧主要構成部分。

當應用程序通過 Socket 接口發(fā)送數(shù)據(jù)包,數(shù)據(jù)包會被網(wǎng)絡協(xié)議棧從上到下進行逐層處理后,才會被送到網(wǎng)卡隊列中,隨后由網(wǎng)卡將網(wǎng)絡包發(fā)送出去。

而在接收網(wǎng)絡包時,同樣也要先經(jīng)過網(wǎng)絡協(xié)議棧從下到上的逐層處理,最后才會被送到應用程序。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

CPU親和度通過限制進程或線程可以運行的CPU核心集合,使得它們只能在指定的CPU核心上執(zhí)行。這可以減少CPU緩存的失效次數(shù),提高緩存命中率,從而提升系統(tǒng)性能。

關鍵字: Linux 嵌入式

在Linux系統(tǒng)性能優(yōu)化中,內(nèi)存管理與網(wǎng)絡連接處理是兩大核心領域。vm.swappiness與net.core.somaxconn作為關鍵內(nèi)核參數(shù),直接影響系統(tǒng)在高負載場景下的穩(wěn)定性與響應速度。本文通過實戰(zhàn)案例解析這兩個...

關鍵字: Linux 內(nèi)存管理

對于LLM,我使用b谷歌Gemini的免費層,所以唯一的成本是n8n托管。在使用了n8n Cloud的免費積分后,我決定將其托管在Railway上(5美元/月)。然而,由于n8n是開源的,您可以在自己的服務器上托管它,而...

關鍵字: 人工智能 n8n Linux

在Linux系統(tǒng)管理中,權限控制是安全運維的核心。本文通過解析/etc/sudoers文件配置與組策略的深度應用,結合某金融企業(yè)生產(chǎn)環(huán)境案例(成功攔截98.7%的非法提權嘗試),揭示精細化權限管理的關鍵技術點,包括命令別...

關鍵字: Linux 用戶權限 sudoers文件

Linux內(nèi)核中的信號量(Semaphore)是一種用于資源管理的同步原語,它允許多個進程或線程對共享資源進行訪問控制。信號量的主要作用是限制對共享資源的并發(fā)訪問數(shù)量,從而防止系統(tǒng)過載和數(shù)據(jù)不一致的問題。

關鍵字: Linux 嵌入式

在云計算與容器化技術蓬勃發(fā)展的今天,Linux網(wǎng)絡命名空間(Network Namespace)已成為構建輕量級虛擬網(wǎng)絡的核心組件。某頭部互聯(lián)網(wǎng)企業(yè)通過命名空間技術將測試環(huán)境資源消耗降低75%,故障隔離效率提升90%。本...

關鍵字: Linux 云計算

在Linux內(nèi)核4.18+和主流發(fā)行版(RHEL 8/Ubuntu 20.04+)全面轉向nftables的背景下,某電商平臺通過遷移將防火墻規(guī)則處理效率提升40%,延遲降低65%。本文基于真實生產(chǎn)環(huán)境案例,詳解從ipt...

關鍵字: nftables Linux

在Linux設備驅動開發(fā)中,等待隊列(Wait Queue)是實現(xiàn)進程睡眠與喚醒的核心機制,它允許進程在資源不可用時主動放棄CPU,進入可中斷睡眠狀態(tài),待資源就緒后再被喚醒。本文通過C語言模型解析等待隊列的實現(xiàn)原理,結合...

關鍵字: 驅動開發(fā) C語言 Linux

在Unix/Linux進程間通信中,管道(pipe)因其簡單高效被廣泛使用,但默認的半雙工特性和無同步機制容易導致數(shù)據(jù)競爭。本文通過父子進程雙向通信案例,深入分析互斥鎖與狀態(tài)機在管道同步中的應用,實現(xiàn)100%可靠的數(shù)據(jù)傳...

關鍵字: 管道通信 父子進程 Linux

RTOS :RTOS的核心優(yōu)勢在于其實時性。它采用搶占式調(diào)度策略,確保高優(yōu)先級任務能夠立即獲得CPU資源,從而在最短時間內(nèi)完成處理。RTOS的實時性是通過嚴格的時間管理和任務調(diào)度算法實現(xiàn)的,能夠滿足對時間敏感性要求極高的...

關鍵字: Linux RTOS
關閉