国产毛多水多高潮高清,久热这里只有精品视频6,国内精品久久久久久久久电影网,国产男同志CHINA69,精品999日本久久久影院,人人妻人人澡人人爽人人精品,亚洲中文无码永久免

25张图,一万字,拆解Linux网络包发送过程(超级详细~)-趣玩体育APP下载IOS

25张图,一万字,拆解Linux网络包发送过程(超级详细~)

2026-01-19 02:20:23投稿人:利升體育官方官網(wǎng)(臨沂)有限公司圍觀7292663 評論

25張圖,一萬字  ,拆解Linux網(wǎng)絡(luò)包發(fā)送過程(超級詳細~)

半年前我以源碼的方式描述了網(wǎng)絡(luò)包的接收過程 。之后不斷有粉絲提醒我還沒聊發(fā)送過程呢 。好 ,安排!

在開始今天的文章之前 ,我先來請大家思考幾個小問題 。

  • 問1 :我們在查看內(nèi)核發(fā)送數(shù)據(jù)消耗的 CPU 時,是應該看 sy 還是 si  ?
  • 問2 :為什么你服務器上的 /proc/softirqs 里 NET_RX 要比 NET_TX 大的多的多?
  • 問3 :發(fā)送網(wǎng)絡(luò)數(shù)據(jù)的時候都涉及到哪些內(nèi)存拷貝操作  ?

這些問題雖然在線上經(jīng)??吹?,但我們似乎很少去深究。如果真的能透徹地把這些問題理解到位 ,我們對性能的掌控能力將會變得更強 。

帶著這三個問題 ,我們開始今天對 Linux 內(nèi)核網(wǎng)絡(luò)發(fā)送過程的深度剖析 。還是按照我們之前的傳統(tǒng),先從一段簡單的代碼作為切入 。如下代碼是一個典型服務器程序的典型的縮微代碼 :

int main(){  fd = socket(AF_INET, SOCK_STREAM, 0); bind(fd, ...); listen(fd, ...); cfd = accept(fd, ...); // 接收用戶請求 read(cfd, ...); // 用戶請求處理 dosometing();  // 給用戶返回結(jié)果 send(cfd, buf, sizeof(buf), 0);}

今天我們來討論上述代碼中,調(diào)用 send 之后內(nèi)核是怎么樣把數(shù)據(jù)包發(fā)送出去的。本文基于Linux 3.10,網(wǎng)卡驅(qū)動采用Intel的igb網(wǎng)卡舉例  。

一 、Linux 網(wǎng)絡(luò)發(fā)送過程總覽

我覺得看 Linux 源碼最重要的是得有整體上的把握 ,而不是一開始就陷入各種細節(jié) 。

我這里先給大家準備了一個總的流程圖 ,簡單闡述下 send 發(fā)送了的數(shù)據(jù)是如何一步一步被發(fā)送到網(wǎng)卡的。


25張圖
,一萬字
,拆解Linux網(wǎng)絡(luò)包發(fā)送過程(超級詳細~)

在這幅圖中,我們看到用戶數(shù)據(jù)被拷貝到內(nèi)核態(tài) ,然后經(jīng)過協(xié)議棧處理后進入到了 RingBuffer 中。隨后網(wǎng)卡驅(qū)動真正將數(shù)據(jù)發(fā)送了出去 。當發(fā)送完成的時候 ,是通過硬中斷來通知 CPU  ,然后清理 RingBuffer 。

因為文章后面要進入源碼,所以我們再從源碼的角度給出一個流程圖 。


25張圖,一萬字,拆解Linux網(wǎng)絡(luò)包發(fā)送過程(超級詳細~)

雖然數(shù)據(jù)這時已經(jīng)發(fā)送完畢 ,但是其實還有一件重要的事情沒有做 ,那就是釋放緩存隊列等內(nèi)存