精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Linux性能調優之內核網絡棧發包收包認知

系統 Linux
在 Linux 系統中,網絡數據包的接收發送是一個涉及硬件、驅動、內核協議棧的復雜協作過程。很多開發者可能只關注應用層的網絡調用(如 socket 編程),卻對內核底層如何 “迎接” 和 “處理”,發送數據包知之甚少。

內核網絡棧的認知

在 Linux 系統中,網絡數據包的接收發送是一個涉及硬件、驅動、內核協議棧的復雜協作過程。很多開發者可能只關注應用層的網絡調用(如 socket 編程),卻對內核底層如何 “迎接” 和 “處理”,發送數據包知之甚少。實際上涉及到一些調優,解決網絡指標飽和或者異常的情況都需要對底層有一定的了解,同時在使用 ebpf 進行網絡性能觀測的時候,主要是通過一些內核態和用戶的系統調用進行埋點,對數據進行匯總分析,所以對內核的認知是必不可少的。

內核收包機制認知

這里將從內核收包前的準備工作入手,一步步拆解數據包到達后的完整處理流程,理清 Linux 網絡棧的核心邏輯。

一、收包前的準備:內核如何 “迎接” 數據包?

在網卡正式接收第一個數據包之前,Linux 內核需要完成一系列初始化和注冊操作,為后續高效處理數據包做好鋪墊。這 4 項準備工作缺一不可,直接決定了后續收包的效率和穩定性。這部分工作是在系統啟動之后完成的。

1.創建軟中斷處理線程:ksoftirqd

內核首先會創建一個特殊的內核線程 ——ksoftirqd,每個 CPU 核心對應一個實例(比如 CPU0 對應的線程是ksoftirqd/0)。創建時會為其綁定 “軟中斷處理” 的核心邏輯,它的核心職責是:

  • 接管 “耗時的數據包處理工作”(如協議解析、數據分發);
  • 避免硬中斷長時間占用 CPU(硬中斷優先級高,若處理耗時會阻塞其他任務)。
[root@liruilongs.github.io]-[~]$ ps -ef | grep   ksoftirqd | grep -v grep
root          11       2  0 8月03 ?       00:00:00 [ksoftirqd/0]
root          17       2  0 8月03 ?       00:00:00 [ksoftirqd/1]
root          22       2  0 8月03 ?       00:00:00 [ksoftirqd/2]
root          27       2  0 8月03 ?       00:00:00 [ksoftirqd/3]
[root@liruilongs.github.io]-[~]$

簡單來說,ksoftirqd是內核專門為 “網絡軟中斷” 配備的 “打工人”,后續數據包的核心處理都靠它。這里的軟中斷是什么,后面我們會講。

2.協議棧注冊:讓內核 “認識” 所有協議

Linux 內核支持ARP、ICMP、IP、UDP、TCP等多種網絡協議,但內核不會 “憑空識別” 這些協議,每個協議在初始化時,都需要主動將自己的數據包處理函數注冊到內核的 協議鏈表 中。

舉幾個關鍵協議的注冊例子:

  • UDP 協議:注冊udp_rcv()函數,作為 UDP 數據包的 “入口處理器”;
  • TCP 協議(IPv4 場景):注冊tcp_rcv_v4()函數,負責 TCP 數據包的接收邏輯;
  • IP 協議:注冊ip_rcv()函數,處理 IP 頭解析和協議分發(比如判斷數據包是 UDP 還是 TCP)。

這個注冊過程的作用很關鍵:當數據包到達時,內核只需查看數據包的 “協議類型字段”(如 IP 頭中的protocol字段),就能快速找到對應的處理函數,無需遍歷所有協議,極大提升了處理效率,類似于一個 Hash 路由一樣。

3.網卡驅動初始化:打通硬件與內核的 “通道”

網卡是數據包進入系統的 “物理入口”,但它需要驅動程序才能與內核協作。內核會調用網卡對應的驅動初始化函數,完成 3 件核心事:

初始化 DMA(直接內存訪問):配置網卡與內存的 DMA 映射,讓網卡可以直接將數據包寫入內存(無需 CPU 中轉,減少 CPU 開銷);下面為系統啟動對應的內核日志。

下面是內核日志中對應的分配邏輯,沒有CPU 中轉,意味著不需要 MMU 內存管理單元參與,分配的是實際的連續的物理內存,而不是虛擬內存,不存在超售問題,并且是鎖定狀態,不會發生頁面換出,分配即占用。

[root@liruilongs.github.io]-[~]$ sudo dmesg -T | grep DMA
[六 9月 13 19:15:28 2025]   DMA      [mem 0x0000000040000000-0x00000000ffffffff] # 內核劃分DMA內存域(DMA zone),地址范圍1GB-4GB,供網卡等DMA設備直接訪問,對應“網卡驅動初始化→DMA映射配置”環節
[六 9月 13 19:15:28 2025]   DMA32    empty # DMA32內存域為空,該內存域用于僅支持32位地址的老舊DMA設備,當前系統無此類設備,對網卡收包無影響
[六 9月 13 19:15:28 2025]   DMA zone: 12288 pages used for memmap # DMA zone中12288個頁(48MB)用于內存映射表(memmap),內核通過該表管理DMA內存使用狀態,是DMA內存分配的基礎
[六 9月 13 19:15:28 2025]   DMA zone: 0 pages reserved # DMA zone無預留內存,所有內存可用于網卡等DMA設備的數據包緩存,保障收包時內存可用性
[六 9月 13 19:15:28 2025]   DMA zone: 786432 pages, LIFO batch:63 # DMA zone共786432個頁(3072MB=3GB)可用,LIFO batch=63表示內核批量分配內存時一次最多分配63個頁,提升分配效率,為網卡提供充足DMA內存
[六 9月 13 19:15:28 2025] DMA: preallocated 1024 KiB GFP_KERNEL pool for atomic allocations # 預分配1024KB GFP_KERNEL內存池,供內核常規場景的DMA原子分配(非緊急數據包緩存),原子分配確保不能睡眠的場景(如硬中斷)快速獲內存
[六 9月 13 19:15:28 2025] DMA: preallocated 1024 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations # 預分配1024KB DMA zone專屬原子內存池,專門供網卡高并發收包時快速分配內存(如突發流量),避免數據包丟棄
[六 9月 13 19:15:28 2025] DMA: preallocated 1024 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations # 預分配1024KB DMA32 zone原子內存池,因DMA32 zone為空,當前暫未使用,預留供老舊DMA設備使用
[root@liruilongs.github.io]-[~]$

注冊 NAPI 的 poll 函數:將驅動實現的poll函數地址告訴內核,后續軟中斷處理時,內核會通過這個函數輪詢從網卡讀取數據包;

網卡收到數據包后,正常觸發硬中斷(IRQ);CPU 通知內核執行中斷處理程序(ISR),讀取數據包到內存,并喚醒上層協議棧,若數據包密集(如千兆網卡滿速傳輸),會產生大量硬中斷,頻發的上下文切換會增加 CPU 開銷,同時會使CPU 緩存失效。

NAPI (NET API)是為了在高吞吐量場景下減少硬中斷次數,所以 NAPI通過 “硬中斷觸發 + 軟中斷輪詢” 的混合模式平衡效率與實時性,而 poll 函數正是輪詢階段的核心執行者。poll 函數由網卡驅動實現,內核通過注冊機制 “記住” 這個函數的地址,以便在軟中斷中調用。注冊過程本質是將驅動的硬件操作邏輯接入內核的網絡中斷處理框架。

配置硬件參數:設置網卡的 MAC 地址、雙工模式(全雙工 / 半雙工)、傳輸速率(如 1Gbps)等基礎參數。

[root@liruilongs.github.io]-[~]$ ifconfig   enp3s0
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.12.191.125  netmask 255.255.240.0  broadcast 10.12.191.255
        inet6 fe80::f816:3eff:fe76:29e7  prefixlen 64  scopeid 0x20<link>
        ether fa:16:3e:76:29:e7  txqueuelen 1000  (Ethernet)
        RX packets 8800  bytes 12120818 (11.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1431  bytes 130773 (127.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@liruilongs.github.io]-[~]$

這一步相當于 “打通網卡與內核的通信通道”,讓硬件具備接收數據包的能力。

4.啟動網卡:配置隊列與中斷

驅動初始化完成后,內核會將網卡從 “down” 狀態切換到 “up” 狀態(即啟動網卡),同時完成兩項關鍵配置:

分配 RX/TX 隊列:通常為每個 CPU 核心分配獨立的接收隊列(RX 隊列)和發送隊列(TX 隊列)(即 RSS 隊列技術),實現數據包的負載均衡,避免單隊列成為性能瓶頸;

查看通道信息,網卡的 “通道” 是硬件層面的數據處理隊列,用于將網絡收發任務分配到不同 CPU 核心,實現并行處理以提升吞吐量。

[root@liruilongs.github.io]-[~]$ ethtool -l  enp3s0
Channel parameters for enp3s0:
Pre-set maximums:    # 硬件支持的最大隊列數(驅動或固件限制)
RX:             n/a   # 接收隊列最大數:不支持獨立RX隊列(n/a = not applicable)
TX:             n/a   # 發送隊列最大數:不支持獨立TX隊列
Other:          n/a     # 其他隊列(如管理隊列)不支持
Combined:       1     # 組合隊列(同時處理RX和TX)最大數:1

Current hardware settings:  # 當前生效的隊列配置
RX:             n/a   # 當前未啟用獨立RX隊列
TX:             n/a   # 當前未啟用獨立TX隊列
Other:          n/a   # 當前未啟用其他隊列
Combined:       1     # 當前啟用1個組合隊列

上面的配置可以看出張網卡(虛擬化環境中的網卡, KVM 的 virtio-net)不支持獨立的 RX/TX 隊列,而是使用 “組合隊列”(Combined)同時處理接收和發送數據,當前配置了 1 個組合隊列

通過 sys 偽文件系統查看網卡的 “通道” 信息,可以看到 “通道” 的數量為 1,即 1 個 RX 隊列和 1 個 TX 隊列。

[root@developer ~]# ls /sys/class/net/enp3s0/queues/
rx-0  tx-0
[root@developer ~]#

確認網卡類型:

[root@liruilongs.github.io]-[~]$ ethtool -i  enp3s0 | grep vir
driver: virtio_net
[root@liruilongs.github.io]-[~]$

注冊硬中斷處理函數:將網卡的 “數據包到達中斷” 與內核中的中斷處理函數綁定,當網卡收到數據時,能觸發 CPU 響應硬中斷,網卡中斷的觸發流程。

  • 硬件層面:網卡收到數據包后,通過 PCIe 總線向 CPU 發送中斷請求(IRQ)信號;
  • CPU 層面:CPU 響應中斷,暫停當前任務,跳轉到內核預設的中斷處理入口;
  • 內核層面:內核通過中斷向量號(IRQ 號)找到對應的處理函數(ISR)并執行。

實際上就是將網卡的硬件中斷信號與內核中的中斷服務程序(ISR)建立關聯,讓內核知道 “哪個 IRQ 號對應哪個網卡的哪個事件(如數據包到達)”。

至此,收包前的準備工作全部完成,內核開啟網卡的硬中斷,進入 “等待數據包到達” 的狀態。

二、數據包到達后:內核如何 “處理” 數據包?

當外部數據包通過網線到達網卡時,Linux 內核會啟動一套 “流水線式” 的處理流程,從硬件接收到底層協議解析,再到應用層分發,每一步都分工明確。

深入理解Linux網絡: 修煉底層內功,掌握高性能原理 (張彥飛)深入理解Linux網絡: 修煉底層內功,掌握高性能原理 (張彥飛)

第一步:網卡 DMA 寫入內存,觸發硬中斷

網卡接收到物理層的以太網幀后,不會直接通知 CPU “幫忙”,而是通過之前配置的 DMA 通道,直接將數據包寫入內存中 RX 隊列對應的 RingBuffer(環形緩沖區) ,這個過程完全不需要 CPU 參與,極大減少了 CPU 的負擔。

ethtool -g 用于查看網卡的硬件環形緩沖區(Ring Buffer)參數。

[root@liruilongs.github.io]-[~]$ ethtool -g  enp3s0
Ring parameters for enp3s0:
Pre-set maximums:    # 硬件支持的最大緩沖區數量(驅動/固件限制)
RX:             2048  # 接收環形緩沖區最大可配置數量:2048個
RX Mini:        n/a   # 小數據包接收緩沖區:不支持(n/a = not applicable)
RX Jumbo:       n/a   # 巨型幀接收緩沖區:不支持
TX:             2048  # 發送環形緩沖區最大可配置數量:2048個

Current hardware settings:  # 當前生效的緩沖區配置
RX:             2048  # 當前接收緩沖區數量:2048個
TX:             2048  # 當前發送緩沖區數量:2048個

該網卡支持獨立的接收(RX)發送(TX)環形緩沖區;當前接收和發送緩沖區均配置為 2048 個(已達硬件最大限制);并且不支持 小數據包,巨型幀 的專用緩沖區(僅用通用緩沖區處理所有包)。

單個緩沖區的大小通常與網卡的 MTU(最大傳輸單元)匹配,計算公式為:單緩沖區大小 ≈ MTU + 協議頭部開銷(約 18-42 字節)

[root@liruilongs.github.io]-[~]$ ip link show enp3s0 | grep mtu
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc tbf state UP mode DEFAULT group default qlen 1000

MTU 為 1500 ,所以總 DMA 物理內存估算,計算該網卡的 DMA 內存總占用:

  • 接收緩沖區:2048 個 × 1538 字節 ≈ 3.07 MB;
  • 發送緩沖區:2048 個 × 1538 字節 ≈ 3.07 MB。

總計:約 6.14 MB(實際可能略大,因驅動會預留少量管理內存)。

當 RingBuffer 滿的時候,新來的數據包將被去棄。使? iconfig 命令查看?卡的時候,可以看到??有個overruns

[root@liruilongs.github.io]-[~]$ ifconfig enp3s0 | grep over
        RX errors 0  dropped 0  overruns 0  frame 0
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@liruilongs.github.io]-[~]$

表?因為環形隊列滿被丟棄的包數。如果發現有丟包,可能需要通過ethtool命令來加?環形隊列的長度。

也可以通過 ethtool -S enp3s0  的  rx_queue_0_drops 指標來查看。

[root@liruilongs.github.io]-[~]$ ethtool -S enp3s0 
NIC statistics:
     rx_queue_0_packets: 49137
     rx_queue_0_bytes: 69848865
     rx_queue_0_drops: 0
     rx_queue_0_xdp_packets: 0
     rx_queue_0_xdp_tx: 0
     rx_queue_0_xdp_redirects: 0
     rx_queue_0_xdp_drops: 0
     rx_queue_0_kicks: 0
     tx_queue_0_packets: 13662
     tx_queue_0_bytes: 935165
     tx_queue_0_xdp_tx: 0
     tx_queue_0_xdp_tx_drops: 0
     tx_queue_0_kicks: 0
[root@liruilongs.github.io]-[~]$

通常很少有修改的需求,隊列不是越長越好,過長會增加數據延遲(數據包在隊列中等待時間變長),通常調整為 512~2048(根據業務場景:高吞吐量場景可稍大,低延遲場景需偏小)

如果是小數據包,數據包寫入完成后,網卡會向 CPU 發送一個硬中斷請求(IRQ),相當于告訴 CPU:“有新數據包到了,快處理!”

如果是大數據包,大流量,修改隊列長度 2048 時,可能要積累 670 個包才觸發一次 NAPI 輪詢;若隊列長度增至 5242,可能要積累 2048 個包才處理,即位于第一個緩存區的數據包和第2048個緩存區的數據包在同一時間被處理,對第一個緩存區的數據就造成了延遲。

這里積累的數據觸發機制通過 NAPI 權重(napi weight)來控制,本質是 單次輪詢最多處理的數據包上限。當隊列中積累的數據包數量達到或接近這個值時,NAPI 會觸發處理。 默認是 64。

[root@developer ~]# cat /sys/module/virtio_net/parameters/napi_weight
64
[root@developer ~]#

需要說明的是 napi_weight 是 “上限”,不是 “觸發閾值”。NAPI 輪詢的觸發閾值(即積累多少個數據包才會觸發一次輪詢處理)控制還有一個影響參數,即 內核全局預算(netdev_budget)netdev_budget 限制一次軟中斷中所有 NAPI 實例處理的數據包總數,即所有的網卡,避免單個軟中斷占用 CPU 過久。 默認值為 300。

[root@developer ~]# sysctl net.core.netdev_budget
net.core.netdev_budget = 300
[root@developer ~]#

權重是針對單個隊列的,而預算 netdev_budget限制了一次軟中斷處理周期內所有NAPI實例總共能處理的數據包數量,防止軟中斷過長時間占用CPU。

第二步:CPU 響應硬中斷,觸發軟中斷

CPU 收到硬中斷請求后,會暫停當前正在執行的任務,切換到內核態,執行之前注冊的硬中斷處理函數。但這里有個關鍵設計:硬中斷處理函數非常 “輕量化”,只做兩件小事:

  • 告知網卡 “我已收到中斷通知”,避免網卡重復觸發中斷;
  • 向內核發起網絡接收軟中斷請求(NET_RX_SOFTIRQ),將后續的 “數據包解析、協議處理” 等耗時操作,交給軟中斷處理。

為什么硬中斷處理要 “輕量化”?因為硬中斷的優先級最高,若處理耗時會阻塞其他高優先級任務(如系統調用、其他硬件中斷),影響系統響應性。

/proc/softirqs  文件輸出展示了系統中軟中斷(Software Interrupt)在各個 CPU 核心上的觸發次數

[root@developer ~]# cat /proc/softirqs 
                    CPU0       CPU1       CPU2       CPU3       
          HI:          0          5          1          0
       TIMER:      19258      14213      16893      24588
      NET_TX:          0          0          2          2
      NET_RX:       3559       1626       1311       2046
       BLOCK:      15548          0          0          0
    IRQ_POLL:          0          0          0          0
     TASKLET:       1681        225        164       1710
       SCHED:      23419      20707      23057      31402
     HRTIMER:          0          0          0          0
         RCU:      33341      32536      31459      34107
[root@developer ~]#

NET_TX 和 NET_RX 分別是 “發送” 和 “接收” 對應在每個CPU核心的軟中斷,分別對應 “發送” 和 “接收” 數據包的處理。

第三步:ksoftirqd 處理軟中斷,讀取數據包

ksoftirqd 線程會周期性檢查內核的軟中斷請求隊列,當發現 NET_RX_SOFTIRQ 軟中斷時,會立即開始工作:

  • 關閉硬中斷:避免處理軟中斷時被新的硬中斷打斷(防止數據競爭,保證數據一致性);
  • 調用 poll 函數讀包:通過驅動注冊的poll函數,從 RX 隊列的 RingBuffer 中讀取數據包,并將其封裝成內核統一的sk_buff結構體(sk_buff是內核中描述數據包的 “標準容器”,包含數據包的所有信息,如協議頭、數據內容、長度等);
  • 開啟硬中斷:數據包讀取完成后,重新開啟硬中斷,允許接收新的數據包。

軟中斷處理時,單次調用 NAPI 的 poll 函數,循環處理數據包(數量不超過 weight 和 netdev_budget 的最小值),若本次讀了閾值內的包(packets_read=64),即使 RX_Ring 還有數據,也會退出循環,避免單次 poll 占用 CPU 過久。

通過 proc/interrupts 可以看到 虛擬網卡(virtio3)的 數據請求隊列中斷(req.0 表示第 0 個數據隊列,負責網卡的數據包接收 / 發送)。

[root@developer ~]# cat /proc/interrupts | grep req
 81:      16363          0          0          0   ITS-MSI 2097153 Edge      virtio3-req.0

對應的中斷親和性,即中斷發生在那個CPU,可以通過中斷號查看,smp_affinity(中斷親和性)控制 “該中斷允許在哪些 CPU 核心上運行”,值為十六進制:

[root@developer ~]# cat /proc/irq/81/smp_affinity
f
[root@developer ~]#

十六進制 f = 二進制 1111,對應系統的 4 個 CPU 核心(CPU0~CPU3)。

這一步完成了 “從硬件緩沖區到內核緩沖區” 的數據包轉移,為后續的協議解析做好準備。

通過 top 命令可以看到 每個CPU 核心的 軟中斷(si)/硬中斷(hi)的使用率。

top - 16:03:56 up  3:37,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 228 total,   1 running, 227 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
%Cpu1  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
%Cpu2  :  0.3 us,  0.3 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
%Cpu3  :  0.3 us,  0.0 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :   6657.9 total,   5398.1 free,    734.6 used,    700.4 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   5923.4 avail Mem

第四步:協議棧解析,分發到應用層

poll函數將sk_buff交給內核協議棧后,協議棧會按 “從下到上” 的順序逐層解析數據包,就像 “拆快遞” 一樣,一層一層揭開數據包的 “包裝”:

  1. IP 層處理:調用ip_rcv()函數解析 IP 頭,檢查 IP 地址、校驗和等信息,然后根據 IP 頭中的protocol字段,判斷數據包的上層協議(如 UDP 對應 17,TCP 對應 6);
  2. 傳輸層處理:
  • 若為 UDP 包:調用udp_rcv()函數解析 UDP 頭,檢查端口號,然后通過 socket 將數據分發給對應的應用進程;
  • 若為 TCP 包:調用tcp_rcv_v4()函數解析 TCP 頭,處理 TCP 連接狀態(如三次握手、重傳、流量控制),最后將數據通過 socket 交給應用進程。

至此,一個數據包從 “到達網卡” 到 “被應用進程接收” 的完整流程就結束了。

內核發包機制認知

網絡發包的核心邏輯是 用戶進程發起請求,內核協議棧分層處理,最終通過網卡硬件發送數據。

深入理解Linux網絡: 修煉底層內功,掌握高性能原理深入理解Linux網絡: 修煉底層內功,掌握高性能原理

一、發包前的準備工作:發送隊列 RingBuffer 的構建

發包同樣是一個涉及用戶態、內核態多層協作的復雜過程,在實際的發包之前,內核會在網卡啟動之后也做一些發包相關的準備,主要是前面我們講到的分配傳輸隊列 RingBuifer的過程。

不同的網卡驅動實現不同,會分配兩個環形數組

  • 一個用于內核使用(分配虛擬內存)
  • 一個用于網卡硬件使用,分配的是連續的物理內存(DMA)

在后面的發包過程中會進行對應的地址映射,這兩個環形數組中相同位置的指針都將指向同?個skb(數據包的內核結構體),內核往對應 skb 地址寫數據,網卡硬件就能共同訪問同樣的數據,負責發送。

二、用戶進程發起請求,內核協議棧分層處理

1.用戶進程:發起發送請求

用戶進程通過 sendto系統調用(或 send/write)發起網絡發送,下面的是一個Python 的Demo,從 Python 標準庫的 socket 模塊封裝,最終觸發操作系統的 send 系統調用。

import socket
# 創建TCP socket(內核創建對應的socket對象)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接(內核完善socket對象的源/目標地址信息)
sock.connect(("110.242.69.21", 80))
# 準備發送數據
request_data = ()
# 調用send系統調用(內核查找socket對象并構造msghdr結構體)
bytes_sent = sock.send(request_data.encode())
# 接收響應
response = sock.recv(4096)
# 關閉連接(內核銷毀socket對象)
sock.close()

此時進程從用戶態切換到內核態,內核會執行兩項核心操作:

  • 查找對應的 socket 對象(標識 TCP/UDP 連接的源 IP、目標 IP、源端口、目標端口);
  • 構造 msghdr 結構體(封裝待發送消息的地址信息、數據長度等元數據)。

之后會進入內核網絡協議棧分層處理。

2.協議棧分層處理(內核態):從傳輸層到網絡設備

內核態的協議棧處理遵循 TCP/IP 分層模型,從傳輸層到網絡層、鄰居子系統、網絡設備子系統,逐步完成數據封裝與轉發。

傳輸層(TCP 處理):

首次內存拷貝與淺拷貝,內核調用 tcp_sendmsg 函數處理傳輸層邏輯,核心操作包括:

  • 申請skb(Socket Buffer,內核中存儲網絡數據的緩沖區),并將用戶態數據拷貝到skb;
  • 進行滑動窗口管理(控制數據發送速率,避免對端接收緩沖區溢出);
  • 設置 TCP 頭部(如源端口、目標端口、序列號、確認號等,保證 TCP 可靠傳輸)。

這一步會涉及兩次關鍵的內存拷貝操作:

  1. 第一次拷貝(必需,深拷貝):內核先申請 skb(Socket Buffer,內核中存儲網絡數據的專用緩沖區),再將用戶態傳遞的數據包拷貝到 skb 中。該拷貝的開銷隨數據量增大而顯著增加;
  2. 第二次拷貝(必需,淺拷貝):為保證 TCP 可靠傳輸(當對端未返回 ACK 時需重發數據),內核會克隆 skb 的 “描述符”(生成新的 skb 副本),但數據本身復用原 skb 的內存(僅拷貝元信息,開銷極低)。

網絡層(IP 處理):

內核調用 ip_queue_xmit 函數處理網絡層邏輯,核心操作包括:

  • 路由查找:根據目標 IP 地址查詢路由表,確定數據發送的下一跳地址
  • 網絡過濾:經過 netfilter 框架(如 iptables 規則),判斷是否允許數據發送;

MTU 檢查與分片:若數據包大小超過網絡設備的 MTU(最大傳輸單元,默認 1500 字節),則觸發 IP 分片,申請多個新 skb,將原 skb 中的數據深拷貝到新 skb 中(第三次拷貝,可選)。

結合傳輸層處理,內核發包的內存拷貝可總結為 “兩次必需 + 一次可選”:

  • 必需拷貝 1:用戶態數據 → 內核態 skb(深拷貝);
  • 必需拷貝 2:傳輸層 skb → 網絡層 skb(淺拷貝,僅描述符);
  • 可選拷貝 3:IP 分片時的深拷貝(僅當數據包超過 MTU 時觸發)。

鄰居子系統:

獲取目標 MAC 地址,內核再次調用 ip_queue_xmit(邏輯分支不同),通過 ARP 協議獲取目標設備的 MAC 地址:

  • 緩存命中:若本地 ARP 緩存中存在 “目標 IP → MAC 地址” 的映射,直接使用該 MAC 地址;
  • 緩存未命中:發送 ARP 請求包(詢問目標 IP 對應的 MAC 地址),待收到 ARP 響應后繼續傳輸。

網絡設備子系統:

這里網絡設備子系統主要用于隊列選擇和觸發軟中斷

隊列選擇:內核調用 dev_queue_xmit,根據網卡的多隊列配置(若支持),將 skb 放入對應的發送隊列(用于負載均衡),談后調用qdise_run 發送數據,如果當前任然持有CPU時間片,那么會 while循環不斷地從隊列中取出 skb 并進?發送(qdisc_restar 調用)。注意,這個時侯其實都占?的是?戶進程的內核態時間。只有當 quota?盡或者其他進程需要CPU的時候才觸發 NET_TX_SOFTIRQ類型軟中斷**(由 ksoftirqd 內核線程處理)。

在這期間,內核會調用網卡驅動程序 dev_hard_start_xmit通過網卡發送數據。

所以為什么說 90% 以上的網絡發包開銷集中在 “內核態處理階段”(協議棧解析、內存拷貝),從這里可以看到僅當內核態進程時間片用盡、需由 ksoftirqd 線程繼續處理發送隊列時,才會觸發 NET_TX 軟中斷,統計到 si(軟中斷 CPU 時間) 中。

這也是在服務器上查看/proc/softirgs,?般 NET_RX 都要? NET_TX ?得多的原因之一。對于接收來說,都要經過 NET_RX 軟中斷,?對于發送來說,只有內核態CPU配額?盡才讓軟中斷上。

3.軟中斷與硬中斷:內核與硬件的異步協作

到這里以后發送數據消耗的CPU就都顯?在軟中斷的CPU使用率里面,不會消耗?戶進程的內核態時間。

軟中斷處理:ksoftirqd 內核線程(每個 CPU 核心對應一個)檢測到 NET_TX 軟中斷后,調用 net_tx_action 函數,再通過 qdisc_run 調度發送隊列(如 FIFO、優先級調度),將 skb 提交給網卡驅動 dev_hard_start_xmit 調用;

硬中斷處理:網卡完成數據發送后,觸發硬中斷(如 igb_msix_ring 函數,因網卡驅動而異),通知內核釋放 skb 內存、清理 RingBuffer,為下一次發送做準備。這里的硬中斷會觸發 NET_RX_SOFTIRQ 軟中斷,即網卡的 “發送完成通知” 與 “接收數據” 觸發的硬中斷,最終都會調用 NET_RX_SOFTIRQ(而非 NET_TX_SOFTIRQ),導致 “發送完成” 的開銷被統計到 NET_RX 中;這也是上面看到 NET_RX 的 CPU 使用率要比 NET_TX 大的原因。

三、網卡驅動的數據包處理

下面我們看下網卡驅動如何發送數據包,在上面的網絡設備子系統中dev_hard_start_xmit調用驅動,驅動銜接硬件

  1. 入口:內核調用驅動,通過dev_hard_start_xmit函數,調用驅動注冊的ndo_start_xmit回調(如igb網卡的igb_xmit_frame),完成“內核到驅動”的交接。
  2. 驅動綁定與DMA映射(igb網卡為Demo)igb_xmit_frame先將skb分配到對應發送隊列,再通過igb_xmit_frame_ringskb綁定到RingBuffer(環形緩沖區)的igb_tx_buffer;隨后igb_tx_map通過dma_map_single,將skb虛擬地址轉成硬件可訪問的物理地址,寫入硬件描述符。
  3. 觸發硬件發送  驅動更新網卡寄存器(如E1000_TDT),通知硬件讀取描述符中的物理地址,通過DMA直接讀內存數據并發送,無需CPU參與,整個流程核心是“DMA映射”和“RingBuffer銜接”,實現軟件到硬件的高效數據傳遞。
責任編輯:武曉燕 來源: 山河已無恙
相關推薦

2011-03-18 11:21:48

2023-03-01 23:56:11

2023-03-10 14:56:37

Linuxconnect系統

2023-03-01 23:53:30

Linuxshutdown進程

2025-03-07 08:30:00

pwruLinux網絡包追蹤

2025-01-17 09:23:31

2023-03-28 15:51:20

2023-03-06 15:43:56

2021-09-17 11:59:21

tcpdump網絡包Linux

2021-09-08 10:21:33

內核網絡包Tcpdump

2009-08-07 10:28:03

2025-05-27 08:20:00

Linux內核參數調優系統

2017-07-21 08:55:13

TomcatJVM容器

2011-03-21 09:35:38

LAMP調優網絡文件

2013-03-20 17:18:07

Linux系統性能調優

2012-06-20 11:05:47

性能調優攻略

2024-08-22 14:47:50

開源Linux網絡抓包工具

2009-07-16 09:02:38

LINUX 2.4.x網絡安全LINUX開發

2022-01-27 23:32:03

Linux操作系統TCP

2021-03-04 08:39:21

SparkRDD調優
點贊
收藏

51CTO技術棧公眾號

亚洲免费黄色录像| 韩国欧美国产1区| a级精品国产片在线观看| 亚洲精品自在久久| 国产精品爱啪在线线免费观看| 天堂在线一区二区三区| h网站久久久| 国产99精品| 亚洲一区二区三区精品在线| 国产精品尤物福利片在线观看| 一边摸一边做爽的视频17国产| 亚洲s色大片| 久久九九99| 亚洲成人激情视频| 91嫩草国产丨精品入口麻豆| 国产又色又爽又黄又免费| 日韩精品丝袜美腿| 亚洲动漫第一页| 亚洲影视中文字幕| fc2ppv在线播放| 91天天综合| 国产日韩av一区| 热久久99这里有精品| 大黑人交xxx极品hd| 日韩脚交footjobhd| 盗摄精品av一区二区三区| 欧美黑人性猛交| 在线免费黄色小视频| 米奇777四色精品人人爽| 精品在线一区二区三区| 上原亚衣av一区二区三区| 精品国产成人av在线免| 青青草在线免费观看| 亚洲神马久久| 日韩av一区二区在线| 青青草成人免费在线视频| 欧美 日韩 国产 成人 在线| 亚洲图片在线| 日韩av在线免费观看一区| 国产三级精品三级在线| 蜜桃精品在线| 国产精品色在线| 国产欧美精品在线| 国产精品xxxx喷水欧美| 亚洲精品亚洲人成在线| 91国内精品野花午夜精品| 日产精品一线二线三线芒果| wwwwww在线观看| 99国产精品免费视频观看| 在线综合视频播放| 国产91沈先生在线播放| 免费看黄网站在线观看| 国产一区不卡在线| 久久久亚洲影院你懂的| 久久精品一区二区免费播放 | 日韩av一区在线观看| 99视频在线观看视频| 99热国产在线| 国产.精品.日韩.另类.中文.在线.播放| 久久久久久有精品国产| 中文字幕丰满乱子伦无码专区| 一本一道久久a久久| 欧美日韩国产激情| 亚洲成人第一| 免费av网站观看| 国产精品亚洲第一| 欧美最猛性xxxx| 999这里只有精品| 日韩电影免费网址| 欧美日韩1区2区| 国产美女在线一区| 91精品专区| 成人午夜视频在线| 国内视频一区二区| 成人黄色片在线观看| 免费在线观看日韩欧美| 欧美精品福利在线| 免费毛片一区二区三区| 久久婷婷蜜乳一本欲蜜臀| 精品国产电影一区二区| 国产精品入口免费软件| av3级在线| 中文字幕一区二区三区蜜月| 精品一区二区久久久久久久网站| 亚洲天堂avav| 蘑菇福利视频一区播放| 国产成人精品在线| 国产在线拍揄自揄拍无码视频| 欧美色蜜桃97| 国产视频精品自拍| 精品国产aⅴ一区二区三区东京热| 亚洲www啪成人一区二区| 亚洲国产毛片aaaaa无费看| 18禁免费观看网站| 成人黄色在线| 日韩免费高清av| 欧美成人福利在线观看| 二区三区不卡| 亚洲国产一二三| av动漫在线观看| 久久www人成免费看片中文| 国产精品高潮呻吟久久| 日本中文字幕一级片| caopo在线| 午夜精品免费在线| 999久久欧美人妻一区二区| 欧美伦理91| 欧美精品久久天天躁| 少妇性l交大片| 成人片免费看| 91精品啪在线观看国产60岁| 久久午夜夜伦鲁鲁片| 国产伦精品一区二区三区在线播放 | 国产精品入口66mio| 国产裸体写真av一区二区| 人妻少妇一区二区三区| 亚洲欧洲色图综合| 日韩激情视频| 欧美黑人猛交| 欧美午夜不卡视频| 69久久久久久| 久久女人天堂| 欧美日韩性生活| 天堂在线资源视频| 国产精品巨作av| 日韩中文字幕国产| 91香蕉视频在线观看视频| 97久久综合精品久久久综合| 日韩视频在线一区二区| 日本激情视频在线| 136国产福利精品导航网址应用| 亚洲天堂av在线免费| 中文字幕永久免费| 成人情趣视频| 91精品国产电影| 欧美黄色aaa| 欧美啪啪一区| 久久久久久香蕉网| 国产精品玖玖玖| 91在线免费播放| 韩国成人一区| 国产一二区在线观看| 欧美国产日产图区| 欧美日韩电影一区二区三区| 欧美美女搞黄| 久久精品国产亚洲高清剧情介绍| 成人免费看黄网站| 99精品国产99久久久久久97| 久久91精品久久久久久秒播| 久久青青草综合| 五月天福利视频| 91看片淫黄大片一级在线观看| 国产精品9999久久久久仙踪林| 国产成人亚洲精品自产在线| 国产福利不卡视频| 99国产视频在线| 午夜成人免费影院| 亚洲国产美女搞黄色| 日本黄色www| 免费看日产一区二区三区| 3d动漫精品啪啪1区2区免费| 一级片手机在线观看| 99伊人成综合| 91av在线播放视频| 性欧美videos另类hd| av成人老司机| 超碰10000| 日韩免费高清视频网站| 亚洲精品一区二区三区影院 | 无码人妻丰满熟妇区五十路 | jizzyou欧美16| 精品国产乱码久久久久久牛牛| 日韩黄色免费观看| 中文字幕免费精品| 欧美精品videofree1080p| 国产成人三级在线播放| 玉足女爽爽91| 91猫先生在线| 久久av日韩| 中文精品99久久国产香蕉| 亚洲天堂网av在线| 国产毛片精品视频| 欧美精品在欧美一区二区| 国产suv精品一区| 91av在线视频观看| 韩日视频在线| 欧美色国产精品| 欧美xxxx精品| 亚洲精品男同| 久久久久久久久久久久久久一区| 久草免费在线视频| 亚洲欧洲日韩国产| 中文字幕人妻丝袜乱一区三区 | 亚洲熟女毛茸茸| 卡一卡二国产精品| 欧美 亚洲 视频| 日本欧美韩国国产| 在线观看视频亚洲| 青青草激情视频| 国产亚洲毛片| 欧美日韩成人一区二区三区| 精品久久99| 欧美成人黑人xx视频免费观看| 国产乡下妇女做爰视频| 91麻豆国产香蕉久久精品| 深夜黄色小视频| 午夜久久tv| 国产成人小视频在线观看| 三级外国片在线观看视频| 精品国产凹凸成av人导航| 国产成人无码一区二区在线播放| 精品中文字幕一区二区小辣椒| 五月天在线免费视频| 国产精品三p一区二区| 国产精品91视频| 91美女精品| 中文字幕精品一区二区精品| 亚洲精品字幕在线观看| 亚洲男同性恋视频| av亚洲天堂网| 亚洲超碰在线观看| 国产精品第七十二页| 在线免费观看污| 亚洲摸下面视频| 国产黄色美女视频| 在线观看一区日韩| 特级西西人体wwwww| 麻豆91小视频| 国产乱子夫妻xx黑人xyx真爽| 午夜激情久久| 国产精品久久久久久久久久久新郎 | 欧美一级黄色片视频| 香蕉精品视频在线观看| 农村寡妇一区二区三区| 曰本三级在线| 国产一区二区日韩| 日韩美女黄色片| 亚洲人xxxx| 天天躁日日躁aaaxxⅹ| 国产精品99久久久久久久女警 | 国产精品aaa| 午夜激情电影在线播放| 欧美贵妇videos办公室| 日本免费中文字幕在线| 日韩高清免费在线| 香蕉视频免费看| 亚洲福利在线看| 国产视频第一页| 欧美日韩在线播放三区四区| 国产天堂第一区| 天天色 色综合| 久久久国产精品黄毛片| 国产精品一卡二卡在线观看| 天天影视综合色| 亚洲一区二区三区高清不卡| 18岁网站在线观看| 国际精品欧美精品| 麻豆av福利av久久av| 136福利精品导航| 91青青草免费观看| 在线精品亚洲欧美日韩国产| 久久久久久久国产| 污视频免费在线观看| 欧美v日韩v国产v| 国产原创视频在线| 91麻豆.com| 波多野结衣a v在线| 99国产精品一区| 亚洲中文字幕一区| 久久综合久久综合久久综合| 欧美黑人欧美精品刺激| 久久精品一区二区三区四区| 一级黄色片大全| 久久蜜桃av一区二区天堂 | 日韩免费不卡视频| 亚洲成人午夜影院| 成年人午夜视频| 粉嫩老牛aⅴ一区二区三区| a一级免费视频| 国产精品丝袜久久久久久app| 激情五月深爱五月| 亚洲色图一区二区| 久久久精品国产sm调教| 欧美日韩中文字幕综合视频| 国产jizz18女人高潮| 一区在线观看视频| 网站永久看片免费| 亚洲嫩草精品久久| 黄色录像一级片| 五月婷婷激情综合| 无码人妻精品一区二区三区9厂| 欧美午夜精品免费| 国产精品一区二区人人爽| 9191国产精品| 全部免费毛片在线播放一个| 日韩精品极品毛片系列视频| 搞黄视频在线观看| 欧美一区二区三区在线电影| 四季av日韩精品一区| 5858s免费视频成人| 99在线观看免费| 亚洲国产精品va在线| 亚洲1卡2卡3卡4卡乱码精品| 欧美精品电影免费在线观看| 欧美精品总汇| 91九色极品视频| 国产精品99久久免费观看| 亚洲日本精品一区| 亚瑟一区二区三区四区| 日本在线播放不卡| 欧美黄色一区| 国产一级做a爰片久久| 国产一区二区三区四区在线观看| 在线免费观看污视频| 国产精品电影院| 日韩综合在线观看| 日韩欧美美女一区二区三区| 青青草视频在线观看| 欧美大片在线看免费观看| 中文在线аv在线| 亚洲最大av网| 欧美久久精品一级c片| 国产视频在线观看一区| 国产精品免费99久久久| 人妻互换免费中文字幕| 麻豆精品新av中文字幕| 精品无码在线视频| 亚洲一区免费在线观看| 在线观看免费观看在线| 亚洲国产日韩精品在线| 亚洲高清视频网站| 中文字幕日韩高清| 日本高清不卡一区二区三区视频| 91久久精品久久国产性色也91| 欧美天堂视频| 国产精品亚洲一区| 亚洲国产视频二区| 日韩福利视频| 一本久久综合| 国产精品久久久久久在线观看| 中文字幕欧美一| 自拍偷拍第八页| 亚洲深夜福利视频| 好久没做在线观看| 亚洲xxxxx| 欧美mv日韩| 免费裸体美女网站| 97se亚洲国产综合自在线不卡| 久久中文字幕在线观看| 欧美一卡二卡在线观看| 91视频在线观看| 国产日韩欧美在线| 欧美亚洲国产激情| 国产精品亚洲a| 国产亚洲女人久久久久毛片| 在线能看的av| 日韩av综合网站| 9999热视频在线观看| 久久国产精品亚洲va麻豆| 亚洲二区视频| www一区二区www免费| 床上的激情91.| 日韩黄色三级视频| 亚洲国产欧美一区二区丝袜黑人| 黄色大片在线| 国产精品乱子乱xxxx| 夜夜精品视频| aaaaaav| 色一情一乱一乱一91av| 丰满人妻一区二区三区四区53| 久久久久一本一区二区青青蜜月 | 91久久久久久久久久久久久| 日本欧美肥老太交大片| 国产欧美激情视频| 亚洲欧美日韩精品久久久久| 国产色视频在线| 久久影院资源网| aaa国产精品视频| 浮妇高潮喷白浆视频| 久久亚洲一区二区三区四区| 一级片一区二区三区| 制服丝袜亚洲精品中文字幕| 超碰在线网址| 国产aⅴ精品一区二区三区黄| 亚洲神马久久| 国产黄色大片免费看| 国产91精品一区| 久久天堂av综合合色蜜桃网| 国产精品成人无码| 中文字幕欧美视频在线| 欧美高清影院| 一区二区三区视频在线播放| 成人一区二区三区视频在线观看 | 欧美国产中文高清| 97久久国产亚洲精品超碰热| 99视频国产精品| 一级片免费网站| 欧美丰满少妇xxxxx| 亚洲人成精品久久久| 最近中文字幕一区二区|