3. 中断基础概念

在深入软中断亲和性调优之前,必须彻底理解中断的底层机制。中断是CPU与外部设备交互的核心事件驱动方式,而硬中断(Hard IRQ)与软中断(SoftIRQ)的分工协作,直接决定了多核网络负载均衡的成败。本节将拆解中断向量表、硬中断处理流程以及软中断的触发与执行。

3.1 硬中断(Hard IRQ)与软中断(SoftIRQ)的本质区别

硬中断由硬件设备(如网卡、磁盘控制器)通过中断控制器(如APIC)向CPU发送电信号触发;软中断则由内核软件在特定时机(如硬中断处理完成后)主动触发,用于处理耗时但非紧急的下半部任务。

对比维度 硬中断(Hard IRQ) 软中断(SoftIRQ)
触发源 硬件设备(网卡、磁盘、定时器) 内核软件(硬中断处理函数、ksoftirqd)
执行上下文 中断上下文(不可睡眠、不可调度) 中断上下文或进程上下文(ksoftirqd)
执行优先级 最高(可抢占进程、可嵌套) 次高(低于硬中断,高于普通进程)
耗时要求 必须极短(微秒级),否则丢包 可稍长(毫秒级),但需避免饥饿
中断号分配 由中断控制器分配(0~255) 内核静态枚举(如NET_RX_SOFTIRQ)
亲和性控制 /proc/irq/<N>/smp_affinity /proc/irq/<N>/smp_affinity + 内核参数
调优关键认知: 网卡收包时,硬中断仅完成“数据从硬件DMA到内存”的极简操作,而协议栈解析、路由查找、socket交付等重头戏全部在软中断中完成。因此,软中断的CPU亲和性配置才是网络负载均衡的核心战场。

3.2 中断向量表(Interrupt Vector Table, IVT)

中断向量表是CPU在实模式或保护模式下用于查找中断处理程序入口地址的跳转表。在x86_64 Linux系统中,中断向量表由IDT(Interrupt Descriptor Table)实现,每个中断向量对应一个门描述符(Gate Descriptor),包含段选择子、偏移地址、DPL(特权级)和类型(中断门/陷阱门)。

中断向量表(IDT)结构示意 中断向量表(Interrupt Descriptor Table, IDT) 向量 0x00 #DE 除零异常 向量 0x01 #DB 调试异常 向量 0x20 IRQ 0 定时器 向量 0x21 IRQ 1 键盘 ... 其他向量 每个向量对应的门描述符(Gate Descriptor)结构 段选择子 偏移地址(低16位) DPL + 类型 偏移地址(高16位) 指向代码段 中断门/陷阱门
关键事实: 在Linux中,0x00~0x1F 为CPU异常和陷阱向量(如缺页 #PF、除零 #DE),0x20~0xFF 为硬件中断向量(IRQ)。网卡中断通常映射到 0x20 之后的某个向量,具体编号由IOAPIC分配。

3.3 中断处理流程:从硬件信号到软中断执行

一次完整的网络中断处理分为上半部(硬中断)和下半部(软中断)两个阶段。上半部必须快速完成,下半部可以延迟处理。

Linux 网络中断处理完整流程 ① 网卡硬件触发中断信号 ② IOAPIC 接收并路由到目标CPU ③ CPU 通过IDT查找中断门 ④ 执行硬中断处理函数(上半部) DMA数据已就绪 → 标记软中断 → 返回 ⑤ 软中断被标记(如 NET_RX_SOFTIRQ) 在 do_softirq() 或 ksoftirqd 中执行 ⑥ 协议栈处理(IP/TCP/UDP)→ socket交付

3.4 硬中断处理函数的关键约束

  • 不可睡眠: 中断上下文没有进程调度实体,调用 schedule() 或 wait_event() 会导致内核崩溃。
  • 不可持有普通锁: 只能使用 spin_lock() 等自旋锁,不能使用 mutex_lock()。
  • 必须极短: 典型硬中断处理时间应 < 10μs,否则会阻塞其他中断或导致网络RX ring buffer溢出。
  • 典型操作: 读取设备状态寄存器、清除中断标志、将skb加入队列、触发软中断。

3.5 软中断的执行时机与ksoftirqd

软中断在以下三种时机被检查并执行:

  1. 硬中断返回前: 在 do_IRQ() 末尾调用 irq_exit() → invoke_softirq()。
  2. 高优先级软中断主动唤醒: 如 raise_softirq() 在硬中断中调用。
  3. ksoftirqd 内核线程: 当软中断执行时间过长或负载过高时,内核唤醒每个CPU上的 ksoftirqd/N 线程(N为CPU编号)在进程上下文中处理剩余软中断。
性能陷阱: 如果软中断在硬中断返回前执行(即 do_softirq() 直接执行),它仍然运行在中断上下文中,此时不能睡眠、不能调度。只有当软中断被推迟到 ksoftirqd 执行时,才处于进程上下文,可以睡眠。网络软中断通常直接在硬中断返回前执行,因此必须保持高效。

3.6 中断亲和性(IRQ Affinity)的配置基础

中断亲和性决定了哪个CPU核心处理特定的硬中断。通过修改 /proc/irq/<IRQ_NUMBER>/smp_affinity 文件,可以指定允许处理该中断的CPU位图。

# 查看网卡中断号(以 eth0 为例)
cat /proc/interrupts | grep eth0

# 输出示例:
#   CPU0    CPU1    CPU2    CPU3
# 32:  12345   67890   11111   22222  IR-PCI-MSI  eth0

# 将中断号32的亲和性设置为仅CPU2和CPU3(位图:1100 = 0x0C)
echo 0x0C > /proc/irq/32/smp_affinity

# 查看当前亲和性掩码
cat /proc/irq/32/smp_affinity
# 输出:00000000,0000000c
重要提示: 硬中断亲和性设置后,软中断默认继承硬中断的CPU亲和性。但现代内核允许通过 /proc/irq/<N>/smp_affinity_list 或 irqbalance 服务进行更精细的软中断分发。后续章节将深入讲解如何利用RPS/RFS/XPS等技术实现软中断的跨核负载均衡。

3.7 本章小结:中断基础与调优的关联

基础概念 与软中断亲和性调优的直接关联
硬中断 vs 软中断 软中断是网络协议栈处理的主战场,其CPU亲和性决定吞吐量
中断向量表(IDT) 每个硬件中断对应唯一向量,亲和性配置基于中断号
硬中断处理流程 硬中断必须极短,否则导致丢包;软中断可延迟但需避免饥饿
ksoftirqd 线程 当软中断负载过高时,ksoftirqd 成为调优对象(优先级、CPU绑定)
smp_affinity 位图 直接控制硬中断和软中断的CPU分布,是负载均衡的起点