3. 中断基础:中断处理流程、中断延迟、中断亲和性

中断是硬件与操作系统之间进行异步通信的核心机制。在高吞吐场景下,中断处理效率直接决定网络与存储设备的极限性能。本节从硬件触发到软件处理的完整路径出发,拆解中断延迟的构成,并引入中断亲和性这一关键调优手段。

3.1 中断处理流程

一次典型的中断处理分为两个阶段:上半部(Top Half) 和 下半部(Bottom Half)。上半部在关闭本地中断的上下文中快速执行,仅完成最必要的硬件确认与数据搬运;下半部在开启中断的上下文中完成协议解析、数据分发等耗时操作。

关键原则:上半部必须极短(通常 < 10 µs),否则会阻塞后续中断,导致中断风暴或丢包。
术语对照:在 Linux 中,上半部对应注册的 irq_handler_t,下半部可通过软中断(SoftIRQ)、tasklet 或工作队列实现。网络收包路径中,NET_RX_SOFTIRQ 是最常见的下半部入口。
中断处理流程(上半部 + 下半部) 硬件设备触发 IRQ 中断控制器(APIC) CPU 接收中断信号 上半部:保存上下文 标记下半部(SoftIRQ) 恢复中断使能 下半部:协议处理 / 数据分发 返回被中断的进程 说明:上半部关闭本地中断执行,下半部在软中断上下文(ksoftirqd)中运行,可被高优先级任务抢占。

3.2 中断延迟的构成与测量

中断延迟(Interrupt Latency)指从硬件产生中断信号到 CPU 开始执行中断服务程序(ISR)第一条指令的时间间隔。在高吞吐系统中,延迟抖动比平均延迟更具破坏性。

延迟阶段 典型耗时 影响因素
硬件传播延迟 10 – 100 ns 总线协议、中断控制器级数
中断屏蔽窗口 0.1 – 10 µs CPU 当前是否关闭中断(cli)
上下文切换 0.5 – 5 µs 寄存器保存、TLB 刷新
ISR 执行(上半部) 1 – 50 µs 设备寄存器访问、数据搬运
下半部调度 1 – 100 µs SoftIRQ 优先级、CPU 负载
性能陷阱:当网络吞吐超过 10 Gbps 时,中断频率可达每秒百万级。若每个中断的上半部耗时 5 µs,则 CPU 将花费超过 50% 的时间仅用于中断进入/退出,无法执行实际业务逻辑。此时必须引入中断合并(Interrupt Coalescing)或轮询模式驱动(NAPI)。

3.3 中断亲和性(IRQ Affinity)

中断亲和性允许将特定中断绑定到指定的 CPU 核心或核心组。合理设置亲和性可以避免中断在多个核心间迁移导致的缓存污染和锁竞争,同时实现负载隔离。

3.3.1 查看与设置亲和性

Linux 通过 /proc/irq/{IRQ_NUM}/smp_affinity 或 /proc/irq/{IRQ_NUM}/smp_affinity_list 控制中断亲和性。前者使用十六进制掩码,后者使用 CPU 列表格式。

# 查看网卡 eth0 的中断号
$ cat /proc/interrupts | grep eth0
 47:  12345678   PCI-MSI 0000:03:00.0  eth0

# 将中断 47 绑定到 CPU 0-3(掩码 0x0f)
$ echo 0f > /proc/irq/47/smp_affinity

# 使用列表格式绑定到 CPU 0 和 CPU 2
$ echo 0,2 > /proc/irq/47/smp_affinity_list

3.3.2 多队列网卡与 RSS

现代网卡支持接收端缩放(RSS),通过硬件哈希将数据流分散到多个 RX 队列,每个队列拥有独立的中断号。此时需要为每个队列设置不同的亲和性,实现多核并行处理。

多队列网卡中断亲和性分配 网卡(NIC) RX Queue 0 RX Queue 1 RX Queue 2 中断控制器 IRQ 47 → Queue 0 IRQ 48 → Queue 1 IRQ 49 → Queue 2 CPU 核心 Core 0 ← IRQ 47 Core 1 ← IRQ 48 Core 2 ← IRQ 49 Core 3(空闲/控制面) 说明:每个 RX 队列绑定到独立 CPU 核心,避免中断在核心间迁移。Core 3 保留给控制面或 其他非数据面任务,实现数据面与控制面隔离。

3.4 中断合并的协同关系

中断亲和性解决的是“中断去哪处理”的问题,而中断合并解决的是“中断频率多高”的问题。两者协同调优才能达到最佳吞吐与延迟平衡:

  • 高吞吐场景:增大合并超时(如 50 µs)或合并帧数(如 16 帧),配合亲和性绑定,减少中断次数,提升批量处理效率。
  • 低延迟场景:减小合并超时(如 5 µs)或关闭合并,配合专用核心处理中断,确保微秒级响应。
  • 混合策略:使用自适应中断合并(如 Intel 的 ITR),根据当前吞吐动态调整合并参数,同时保持亲和性固定。
调优检查清单:
  1. 使用 mpstat -I CPU 观察各核心中断分布是否均衡。
  2. 检查 /proc/interrupts 确认中断是否集中在预期核心。
  3. 使用 ethtool -c eth0 查看当前合并参数(rx-usecs / rx-frames)。
  4. 使用 perf top 确认下半部处理(如 net_rx_action)是否在绑定核心上执行。

3.5 常见误区与避坑

误区 后果 正确做法
将所有中断绑定到 CPU 0 CPU 0 过载,系统软锁 按队列分散到不同核心
中断亲和性与进程亲和性冲突 进程被调度到非中断核心,跨 NUMA 访问 使用 taskset 或 cgroup 统一规划
忽略 BIOS 中断分发设置 硬件强制路由到特定核心 检查 BIOS 中 NUMA 与中断分发选项
合并参数设置过大 延迟飙升,TCP 超时重传 根据应用延迟要求设置上限(通常 ≤ 100 µs)