精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

一区二区三区久久网| 亚洲精品在线观看av| 国产一区二区av| 精品不卡视频| 欧美一区免费看| 国产精品一区而去| 亚洲日本在线视频观看| 一本大道色婷婷在线| 日韩精品xxx| 久久精品久久久久电影| 亚洲中午字幕| 先锋av资源站| 国产一线二线三线女| 67194成人在线观看| 黄色成人美女网站| 青青草手机视频在线观看| 国产精品专区h在线观看| 久久久五月婷婷| a天堂资源在线| 国产精品欧美性爱| 欧美国产精品日韩| 国产成人精品1024| 超碰在线资源| 美国黄色a级片| 欧美性受xxxx白人性爽| 久久综合九色综合欧美就去吻| 91超碰在线| 久久av无码精品人妻系列试探| 久久99久久久久久久噜噜| 韩国精品免费视频| 黄色在线看片| 一级黄色片大全| 国产日韩欧美黄色| 夜夜精品浪潮av一区二区三区| 国产精品xnxxcom| 欧美日韩乱国产| 伊人久久大香线蕉精品| 日韩一区二区电影在线| 国产精品亚洲综合色区韩国| 成人精品一区二区三区校园激情| 做a视频在线观看| 国自产精品手机在线观看视频| 久久影院午夜论| 免费看日产一区二区三区| 日本熟妇毛耸耸xxxxxx| 欧美深深色噜噜狠狠yyy| 欧美精品aⅴ在线视频| 在线观看视频免费一区二区三区| 午夜性色福利视频| 日本女人性视频| 国产精品18久久久久久首页狼 | 免费在线观看a级片| 久久国产精品偷| 国产日韩高清在线| 日本福利一区| 欧美一级淫片免费视频魅影视频| 久久久精品高清| 国产精品久久视频| 欧美亚男人的天堂| 日韩成人免费看| 中文不卡1区2区3区| 久久精品美女视频| 久久久久久久中文| 91精品国产91久久| 精品电影在线观看| 国产精品夜夜夜| 桃子视频成人app| 成人黄色片在线观看| 中文字幕av不卡在线| 国产欧美精品在线播放| 日韩一区二区影院| 成人免费毛片嘿嘿连载视频| 韩国精品福利一区二区三区| 午夜视频www| 免费观看a级片| av磁力番号网| 2020国产精品视频| 欧美卡1卡2卡| 91最新地址在线播放| 成人综合久久| а√天堂8资源在线官网| 国产无码精品视频| 午夜在线观看av| 国产久一道中文一区| 亚洲网站视频福利| 亚洲精品伦理在线| 日韩福利视频网| 97se亚洲国产一区二区三区| 黑人乱码一区二区三区av| 97人妻精品一区二区三区免| 国产一区二区精品免费| 中文字幕亚洲第一| 性做久久久久久免费观看| 蜜臀av国产精品久久久久| 老牛精品亚洲成av人片| 草莓福利社区在线| 九九热最新视频| 国产艳俗歌舞表演hd| 一二三四中文字幕| 国产精品一二三在线| 亚洲欧洲在线视频| 天天色图综合网| 丁香激情综合国产| 欧美日韩福利| 6080成人| 污污视频在线| 午夜精品久久久久久久99热黄桃 | 婷婷成人综合网| 国产精品99久久久| 欧美一区二区三区另类| 精品视频一二| 污片视频在线免费观看| av无码精品一区二区三区宅噜噜| 91导航在线观看| 亚洲一级免费在线观看| 在线视频不卡一区二区| 国产日韩欧美91| 久久精品视频99| 日韩一级大片在线观看| 亚洲影视资源网| 成人午夜看片网址| 久久精品一区二区国产| 精品美女视频| 日韩五码电影| 咪咪网在线视频| 久久米奇亚洲| xxxwww在线观看| 国产熟妇一区二区三区四区| 538精品视频| 师生出轨h灌满了1v1| 国产精品丝袜久久久久久消防器材| 欧美理论一区二区| 亚洲在线免费视频| 人人澡人人澡人人看欧美| 精品国产依人香蕉在线精品| 精品电影一区二区三区| 欧美日韩一区小说| 亚洲成人免费视频| 亚洲少妇最新在线视频| 91在线一区二区| 粉嫩一区二区三区在线看| 亚洲激情另类| 中文字幕日韩欧美精品高清在线| 偷拍亚洲精品| 成人搞黄视频| 日韩黄色片网站| www.com久久久| 国产精品wwwww| 激情深爱综合网| 8x8ⅹ国产精品一区二区二区| 色噜噜狠狠一区二区三区| 成人3d动漫一区二区三区91| 国产精品扒开腿爽爽爽视频| 97国产一区二区精品久久呦| 欧美刺激性大交免费视频| 视频直播国产精品| 中文字幕久精品免费视频| 精品爽片免费看久久| 亚洲电影免费观看高清完整版在线观看| 欧美色视频在线观看| 91国产丝袜在线播放| 狠狠综合久久av一区二区小说| 婷婷精品在线观看| 亚州av一区| 国产成人精品三级高清久久91| 卡通动漫国产精品| 欧美日韩有码| 婷婷精品进入| 欧美色图首页| 亚洲黄色影院| 麻豆精品视频在线| 国产在线精品一区二区| 国产一区91精品张津瑜| 成人免费观看av| 久久综合色一综合色88| 国产免费观看久久| 亚洲免费在线视频| 亚洲免费伊人电影| 一区二区三区四区中文字幕| 亚洲超丰满肉感bbw| 色婷婷精品大在线视频| 3d成人h动漫网站入口| 亚洲成在人线av| 日韩中文在线中文网在线观看| 欧美精品在线第一页| 国产精品igao视频| 国产区二精品视| 中国成人在线视频| 各处沟厕大尺度偷拍女厕嘘嘘| 国产一级片自拍| 91精品国产自产| 91嫩草|国产丨精品入口| 精人妻无码一区二区三区| www精品国产| 超碰电影在线播放| 欧美男女视频| 精品盗摄女厕tp美女嘘嘘| 在线不卡视频| 国产91丝袜在线18| 国产精品成人网| 欧美性猛交xxxx乱大交退制版| 精品999在线播放| 欧美巨猛xxxx猛交黑人97人| 国产在线观看91精品一区| 日韩av不卡在线播放| 漂亮人妻被中出中文字幕| 9.1在线观看免费| 国产精品美女毛片真酒店| 国产a级免费视频| 在线xxxx| 久久精品色播| 国产手机视频一区二区| 99re成人精品视频| 一本高清dvd不卡在线观看| 亚洲欧美一区二区三区四区 | 中文成人在线| 偷拍欧美精品| 成人丝袜高跟foot| 亚洲成人在线网站| 精品一区二区三区四区| 国产精品久久在线观看| 一区二区视频在线播放| 91小视频在线播放| 日本一区二区三区四区五区 | 免费欧美在线| 亚洲欧洲日产国码二区| 精品欧美久久久| 国产99久久久欧美黑人 | 国产一区二区三区高清| av观看免费在线| 九九热精品免费视频| 国产在线电影| 日韩三级av高清片| 日韩影院精彩在线| 亚洲线精品一区二区三区八戒| 亚洲激情自拍图| 成人综合国产精品| caoporn超碰97| 麻豆91精品91久久久| aⅴ在线视频男人的天堂| 97久久综合区小说区图片区| 免费在线观看一区二区三区| 亚洲h在线观看| 欧美乱大交xxxxx另类电影| 欧美日韩在线精品一区二区三区| 五月天丁香花婷婷| 国产一区二区视频网站| 黄频免费在线观看| 国产一区日韩欧美| 亚洲天堂精品视频| 精品久久久av| 国产精品av免费| 亚洲一二三四五六区| 成人在线免费视频| 九九久久成人| 久久你懂得1024| 亚洲日韩中文字幕在线播放| 国产精品免费视频一区二区| 中国男女全黄大片| 成人毛片在线免费观看| 成人激情自拍| thepron国产精品| 日韩高清有码在线| 欧美日韩综合网| 婷婷丁香综合网| 麻豆传媒在线完整视频| 亚洲a一区二区三区| 亚洲综合一区二区| 亚州成人av在线| 成人在线看视频| 一级黄在线观看| 国产精品白丝av嫩草影院| 94色蜜桃网一区二区三区| 亚洲午夜未删减在线观看| 亚洲一区不卡在线| 国产性猛交普通话对白| 都市激情亚洲一区| 美腿丝袜亚洲三区| 精品美女一区二区三区| 久久精品午夜一区二区福利| 国产探花视频在线播放| 欧美69xxxx| 亚洲黄色高清| 在线观看一区日韩| 久久久久久草| 侵犯稚嫩小箩莉h文系列小说| 美女网站视频在线| 免费av成人在线| 精品亚洲国产视频| www.亚洲成人网| 国产人妖一区二区| 日韩黄色大片| 色婷婷综合久久久中文字幕| 成人动漫在线观看视频| 午夜剧场免费在线观看| 亚洲欧美在线成人| 久久久精品免费观看| 午夜免费日韩视频| av在线免费观看不卡| 美女黄视频在线观看| 蜜桃免费网站一区二区三区| 在线观看久久久久久| 日本美女高潮视频| av免费在线一区二区三区| 亚洲中字在线| 一个人看的www久久| 国产麻花豆剧传媒精品mv在线| 五月天婷婷社区| 狠狠爱综合网| 亚洲大尺度美女在线| 亚洲熟妇av一区二区三区漫画| 亚洲精品国产精品国| 黄色亚洲免费| 亚洲国产日韩欧美在线图片| 日韩欧美亚洲天堂| 三级做a全过程在线观看| 国产亚洲一级| 深夜精品寂寞黄网站在线观看| 99视频免费播放| 欧美日韩在线资源| 麻豆精品国产传媒mv男同| www国产精品视频| 欧美一级片在线免费观看| 岛国av在线网站| 国产欧美一区二区精品性色| 国产精品观看在线亚洲人成网| 农村老熟妇乱子伦视频| 99精品在免费线中文字幕网站一区 | 90岁老太婆乱淫| 9999精品免费视频| 精品久久久久久久久久久| 日本一区免费| www.com在线观看| 久久成人在线| 麻豆成人在线看| 91久久免费视频| 91久久偷偷做嫩草影院电| 91成人看片片| 国产婷婷一区二区三区| 男人资源在线播放| 久久久久久久久蜜桃| 91嫩草免费看| 一区二区日韩在线观看| 校园春色综合网| 国精产品一区一区三区有限在线| av永久免费观看| 久久最新网址| 亚洲精品不卡在线| 黑人玩弄人妻一区二区三区| 欧美特黄不卡| 91精品国产全国免费观看| 中文字幕天天干| 芒果视频成人app| 精品福利樱桃av导航| 日本男女交配视频| 里番在线播放| 亚洲国产精品自拍| 99在线精品免费视频| 国产伦久视频在线观看| 亚洲午夜久久久久中文字幕久| 在线观看成人av| 日本在线观看大片免费视频| 樱花影视一区二区| bt天堂新版中文在线地址| 日本大胆在线观看| 欧美性色xo影院| 亚洲黄色a v| 精品999日本久久久影院| 日韩一二三区不卡| 成人性生活免费看| 宅男在线一区| 色婷婷综合成人av| 欧美日韩人妻精品一区二区三区| 欧美性色综合| 欧美亚洲日本黄色| 中国女人一级一次看片| 国产一区亚洲一区| 蜜桃久久精品乱码一区二区 | 国产电影一区在线| 免费毛片一区二区三区久久久| av免费观看一区二区| 亚洲一二三四区不卡| 我看黄色一级片| 菁菁伊人国产精品| www.xxxx欧美| 日本一级黄色大片| 美女视频黄久久| 日本一区二区三区四区在线观看| 麻豆最新免费在线视频| 色综合网站在线| 呦呦视频在线观看| 一区二区在线| 国产日韩在线看片| 久久米奇亚洲| 欧美色视频日本高清在线观看| 在线观看网站黄| 夜间精品视频| 91精品视频播放| av网站在线播放| 色婷婷综合在线|