4. 传统收包路径:经典中断方式下网卡驱动收包流程与性能开销
在深入 NAPI 之前,必须先理解传统中断驱动收包路径的完整流程。经典方式下,每当网卡接收一个数据包,就会触发一次硬件中断,通知 CPU 暂停当前任务去处理该包。这种“每包必中断”的模式在低速网络时代工作良好,但在高速网络下会引发严重的性能问题。
4.1 经典中断收包全流程
下图展示了从数据包到达网卡到交付给协议栈的完整中断驱动路径:
4.2 各阶段详细开销分析
传统中断路径的每个阶段都引入可量化的 CPU 开销。下表汇总了各环节的主要性能损耗:
| 阶段 | 操作内容 | 主要开销类型 | 相对开销等级 |
|---|---|---|---|
| ① 硬件中断触发 | 网卡向中断控制器发送 IRQ,CPU 保存当前上下文 | 中断上下文切换、Cache 污染 | 高 |
| ② ISR 执行 | 读取中断状态寄存器,标记设备,调度软中断 | 寄存器 I/O 访问、中断屏蔽/解屏蔽 | 中 |
| ③ 软中断调度 | 设置 NET_RX_SOFTIRQ 标志位,触发软中断处理 | 软中断向量查找、ksoftirqd 唤醒 | 低 |
| ④ 软中断处理 | 调用 net_rx_action,从 Ring Buffer 读取 skb | 内存拷贝、skb 分配、链表操作 | 高 |
| ⑤ 协议栈处理 | IP 分片重组、TCP 重组、校验和验证 | CPU 计算、内存访问、锁竞争 | 高 |
| ⑥ 用户态交付 | 将 skb 放入 socket 接收队列,唤醒用户进程 | 进程调度、锁、系统调用 | 中 |
关键指标:在 1 Gbps 网络下,64 字节小包的理论 PPS 约为 1.49 Mpps。传统中断方式每包约消耗 2-5 μs CPU 时间,这意味着单核 CPU 最多只能处理约 200 Kpps,远低于线速。中断频率与包速率成正比,导致 CPU 利用率随 PPS 线性增长。
4.3 中断风暴:性能崩溃的根源
当网络流量增大时,传统中断路径会陷入“中断风暴”恶性循环:
- 高 PPS 触发大量中断:每到达一个数据包,网卡就触发一次硬件中断。
- CPU 被中断淹没:CPU 频繁保存/恢复上下文,实际用于处理数据包的时间比例下降。
- Cache 抖动加剧:中断处理导致 L1/L2 Cache 频繁失效,指令流水线被打断。
- 吞吐量断崖式下降:当中断频率超过 CPU 处理能力时,丢包率急剧上升,有效吞吐量反而下降。
实际案例:在 10 Gbps 网络下,64 字节小包线速为 14.88 Mpps。传统中断方式在单核上最多处理约 200 Kpps,这意味着超过 98.6% 的中断无法被及时处理,导致大规模丢包。这也是为什么现代网卡驱动必须引入 NAPI 轮询机制的根本原因。
4.4 传统中断路径的三大性能开销
将上述分析归纳为三个核心开销维度:
| 开销维度 | 具体表现 | 量化参考(每包) |
|---|---|---|
| 上下文切换开销 | 硬件中断保存/恢复寄存器、TLB 刷新、中断栈切换 | 0.5 - 2 μs |
| Cache 污染开销 | 中断处理代码和数据挤占 L1/L2 Cache,导致应用程序 Cache 命中率下降 | 10% - 30% 应用性能损失 |
| 调度与锁开销 | 软中断调度、ksoftirqd 唤醒、skb 分配锁、协议栈锁竞争 | 1 - 3 μs |
性能优化启示:传统中断路径的核心矛盾在于“中断频率与包速率成正比”。要突破性能瓶颈,必须打破这种线性关系——这正是 NAPI 轮询机制的设计目标:在高速率下将中断转换为轮询,大幅降低每包的中断开销。
4.5 传统路径与 NAPI 路径的初步对比
在进入 NAPI 详细分析之前,先通过下表建立两种路径的宏观对比:
| 对比维度 | 传统中断路径 | NAPI 轮询路径 |
|---|---|---|
| 中断触发频率 | 每包一次硬件中断 | 仅在开始轮询时一次中断 |
| CPU 开销特征 | 中断开销随 PPS 线性增长 | 中断开销固定,轮询开销可控 |
| 高 PPS 表现 | 中断风暴,吞吐量崩溃 | 稳定处理,接近线速 |
| 适用场景 | 低速率网络(< 100 Kpps) | 高速率网络(> 1 Mpps) |
| 公平性 | 各设备公平中断 | 需配额机制防止饿死 |