這張圖詳細描述了 TCP 握手過程中,從客戶端發送 SYN 包到服務器最終建立連接的整個數據流轉過程,包括網卡、內核、進程中的各個環節。下面對每個步驟進行詳細解釋:
客戶端到服務器的初始連接請求
- 客戶端發送 SYN 包:
- 客戶端發起一個 TCP 連接請求,發送 SYN(同步)包到服務器。
- 這個 SYN 包是三次握手的第一步。
網卡驅動
-
進入網卡的 RingBuffer:
- 服務器的網卡接收到來自客戶端的 SYN 包,將其存儲在網卡硬件的 RingBuffer 中。
- RingBuffer 是網卡內置的一個循環緩沖區,用于暫存接收到的數據包。
-
DMA 傳輸:
- 網卡使用 DMA(Direct Memory Access)將數據包從 RingBuffer 傳輸到系統內存中的 DMA 緩沖區。
- DMA 緩沖區位于系統內存,由網卡驅動程序管理。
內核處理
-
硬中斷觸發:
- 當數據包被 DMA 傳輸到系統內存后,網卡觸發硬中斷通知 CPU 數據包已經到達。
- 硬中斷處理程序進行基本處理,如記錄中斷事件,并觸發軟中斷請求。
-
軟中斷處理:
- 軟中斷處理程序(如 NAPI 輪詢函數)將數據包從 DMA 緩沖區讀取,并復制到
sk_buff
結構中。 sk_buff
是內核中用于存儲和管理網絡數據包的數據結構。
- 軟中斷處理程序(如 NAPI 輪詢函數)將數據包從 DMA 緩沖區讀取,并復制到
-
協議棧處理:
- 數據包被存儲在
sk_buff
中,并傳遞給內核的網絡協議棧進行處理。 - 在
netif_receive_skb
函數中,數據包根據其協議類型(如 TCP、UDP、ARP 等)被傳遞到相應的處理函數。
- 數據包被存儲在
TCP 三次握手處理
-
進入半連接隊列:
- 如果數據包是 TCP SYN 包,它將進入服務器的半連接隊列(Syn Queue)。
- 半連接隊列用于存儲尚未完成三次握手的連接請求。
-
完成三次握手:
- 服務器發送 SYN-ACK 包給客戶端,并等待客戶端發送 ACK 包以完成三次握手。
- 當服務器接收到客戶端的 ACK 包后,連接請求從半連接隊列移到全連接隊列(Accept Queue)。
進程處理
- 全連接隊列:
- 全連接隊列用于存儲已完成三次握手的連接請求,等待應用層調用
accept
系統調用來處理這些連接。 - 應用程序調用
accept
后,連接從全連接隊列移到應用層,正式建立連接,準備進行數據傳輸。
- 全連接隊列用于存儲已完成三次握手的連接請求,等待應用層調用
DMA 緩沖區的滿情況和處理方法
DMA 緩沖區滿的處理
-
數據包丟失:
- 當 DMA 緩沖區滿時,新到的數據包無法存儲,將被丟棄。這會導致數據包丟失,特別是在高流量情況下。
-
優化措施:
- 增大 DMA 緩沖區:如果硬件允許,可以通過配置或升級網卡來增大 DMA 緩沖區的大小。
- 調整系統參數:優化內核參數,以增加系統緩沖區的容量,提高整體處理能力。
- 使用多隊列:配置網卡的多隊列機制,使得多個隊列可以并行處理數據包,提高處理效率。
- 流量控制:在高流量情況下,使用流量控制和限流機制,減少數據包丟失。
示例命令
-
調整 RingBuffer 和隊列大小:
bash復制代碼
ethtool -G eth0 rx 4096
-
調整內核參數:
bash復制代碼
sysctl -w net.core.rmem_max=26214400 sysctl -w net.core.wmem_max=26214400
-
調整中斷親和性:
bash復制代碼
echo 1 > /proc/irq/IRQ_NUMBER/smp_affinity
結論
TCP 握手過程中,數據包從網卡接收到系統內存,再到內核處理的整個過程,涉及硬件(如網卡、RingBuffer、DMA)和軟件(如 sk_buff
、協議棧、連接隊列)多個層面的協作。DMA 緩沖區在高流量情況下可能會滿,通過合理的硬件配置和系統優化,可以提高網絡數據包處理能力,減少數據包丟失,保障網絡性能。