
本文主要整理一些自己对Linux网络协议栈的概念性问题QA形式不成体系想到哪里写到哪里1.Linux协议栈如何处理来自网线上的数据帧在linx环境下当以太网线上来一帧数据时SOC通过中断软中断协议栈的机制来处理该数据帧硬件层面 - 网卡如何通知SOC有数据帧到达1.DMA预分配接收缓冲区(Ring Buffer)在系统启动时网卡初始化初始化内核会通知DMA在主内存为网卡预分配一组接收描述符(Rx Descriptor Ring)和对应的缓冲区sk_buff或raw buffer网卡也知道这些缓冲区的物理地址2.数据帧到达 DMA写入当以太网线上有数据帧到达时网卡硬件直接通过DMA将帧内容写入预分配的接收缓冲区无需CPU参与数据搬运3.触发硬件中断IRQDMA写完一帧后网卡会向SOC的中断控制器发送一个硬件中断信号告诉CPU有新数据到了内核层面1.硬中断处理 - Top Half 上半部CPU收到中断后跳转到网卡驱动注册的中断处理函数这种函数一般非常轻量通常只做两件事(因为硬中断上下文不能睡眠所以不做复杂操作)1.禁用网卡的接收中断防止频繁中断后续靠NAPI轮询2.调度软中断触发NET_RX_SOFTIRQ然后立即返回2.软中断处理 - Bottom Half下半部 - NAPI机制Linux使用NAPI(New API)机制来高效处理高速网络流量软中断net_rx_action()被调度执行后:1.调用网卡驱动的poll()函数2.驱动从RX Ring Buffer中批量取出已接收的数据帧3.对每个帧会构造sk_buff(socket buffer)结构体填充协议信息(比如ETH_P_IP),再调用netif_reveive_skb()将buffer送入网络协议栈使用NAPI会再高负载时自动从中断驱动切换为轮询模式避免中断风暴3.协议栈处理netif_receive_skb()根据帧EtherType(比如IPV4ARP)查找对应的上层协议处理函数如果是IP包则调用ip_rvc()如果是ARP包则调用arp_rcv()然后数据包逐层向上交IP-TCP/UDP-Socket4.交给用户进程最终数据被放入socket的接收队列中用户进程调用recv()/read()时从队列中取走数据流程图[以太网帧到达] ↓ [网卡通过 DMA 写入 RX Ring Buffer] ↓ [网卡触发硬件中断 (IRQ)] ↓ [CPU 执行硬中断处理禁用中断 调度软中断] ↓ [软中断执行 net_rx_action → 驱动 poll() 函数] ↓ [批量从 Ring Buffer 取出帧 → 构造 sk_buff] ↓ [调用 netif_receive_skb() → 协议栈 (IP/TCP/UDP)] ↓ [数据进入 socket 接收队列] ↓ [用户进程 recv() 读取数据]2.Linux本机与本机socket通信会走网卡吗1.127.0.0.1本机网络IO需要经过网卡吗不需要经过网卡即使把网卡拔了本机网络还是可以正常使用的。本机网络IO的内核执行流程跨机网络IO的流程2.数据包在内核中是什么走向和外网发送相比流程上有什么区别本机网络 IO 和跨机 IO 比较起来确实是节约了驱动上的一些开销。发送数据不需要进 RingBuffer 的驱动队列直接把 skb 传给接收协议栈经过软中断。但是在内核其它组件上可是一点都没少系统调用、协议栈传输层、网络层等、设备子系统整个走了一个遍。连“驱动”程序都走了虽然对于回环设备来说只是一个纯软件的虚拟出来的东东。3.用本机ip(例如192.168.x.x)和用127.0.0.1性能上有差别吗正确结论是和 127.0.0.1 没有差别都是走虚拟的环回设备 lo。这是因为内核在设置 ip 的时候把所有的本机 ip 都初始化 local 路由表里了而且类型写死 RTN_LOCAL。在后面的路由项选择的时候发现类型是 RTN_LOCAL 就会选择 lo 了。具体分析请参考原文https://www.zhihu.com/question/43590414/answer/19288423383.DPDK是什么?DPDk(Data Plane Development Kit)是一套数据平面开发套件核心目标是绕过Linux协议栈在用户态直接接管网卡进行数据包处理从而实现极致的网络吞吐量和超低延迟在传统的 Linux 网络模型中数据包处理路径长且开销大频繁中断 每收到一个包就触发一次硬件中断CPU 大量时间消耗在中断上下文切换上。内存拷贝 数据从网卡 DMA 到内核空间再拷贝到用户空间至少 2 次内存复制。系统调用 用户程序通过 socket 等系统调用与内核交互涉及模式切换和锁竞争。协议栈开销 完整的 TCP/IP 协议栈处理逻辑复杂不适合纯转发场景。当网络带宽达到 10Gbps、25Gbps 甚至 100Gbps 时CPU 几乎全部被上述开销耗尽无法进行有效的业务处理。DPDK 通过以下关键技术彻底解决了上述瓶颈核心技术原理说明解决的问题UIO / VFIO将网卡的 MMIO 空间和中断映射到用户空间用户态程序可直接读写网卡寄存器。绕过内核驱动消除系统调用开销。PMD (Poll Mode Driver)用户态轮询驱动主动查询网卡收发包队列完全禁用硬件中断。消除中断风暴和上下文切换开销。HugePages使用大页内存2MB/1GB减少 TLB Miss并将内存锁定在物理 RAM 中防止换出。提升内存访问效率保证确定性延迟。Zero-Copy数据包直接在网卡 DMA 缓冲区和用户态应用之间传递无中间拷贝。消除内存复制开销。CPU Affinity Core Pinning将收发包线程绑定到专用 CPU 核上避免调度迁移和缓存失效。最大化单核算力利用率。Batch Processing批量收发包如一次取 32/64 个描述符摊薄单次操作开销。提升指令缓存命中率和吞吐量。DPDK软件架构┌─────────────────────────────────────┐ │ 用户态应用程序 │ ← 你的业务逻辑路由/过滤/DPI等 ├─────────────────────────────────────┤ │ DPDK Libraries (EAL, MBUF, │ ← 环境抽象层、内存池、Ring队列 │ Ring, Mempool, Ethdev...) │ 流分类、加密、压缩等加速库 ├─────────────────────────────────────┤ │ PMD (User-space NIC Drivers) │ ← 用户态网卡驱动Intel/Mellanox/Broadcom等 ├─────────────────────────────────────┤ │ UIO / VFIO / HugePages │ ← 内核旁路机制 ├─────────────────────────────────────┤ │ Linux Kernel │ ← 仅负责启动初始化运行时不参与数据面 └─────────────────────────────────────┘EAL (Environment Abstraction Layer) DPDK 的操作系统负责初始化 HugePages、CPU 亲和性、PCIe 设备探测等底层环境。Mbuf DPDK 的数据包缓冲区结构体类似内核的sk_buff但更轻量高效。Ring Library 无锁环形队列用于多核之间的零拷贝数据传递。Ethdev API 统一的网卡抽象接口屏蔽不同厂商 PMD 的差异。DPDK 就是把原本由内核干的搬包活儿搬到用户态用专用 CPU 核以流水线工厂的方式高效完成让通用服务器也能拥有媲美专用 ASIC 的网络处理能力。