本页目录
中断子系统
覆盖: irq_desc/irq_chip/irq_domain → 中断处理流程 (top/bottom half) → softirq/tasklet/workqueue → threaded IRQ → MSI/MSI-X → APIC/IOMMU 中断重映射 内核版本: 2.6 ~ 6.x
概述
中断子系统是内核中与硬件最紧密耦合的部分。当网卡收到包、磁盘完成 DMA、定时器到期时,硬件通过中断控制器 (APIC/GIC) 向 CPU 发送中断信号。内核的中断子系统负责:路由中断到正确的 CPU、分发到对应的设备驱动 handler、以及 defer 耗时工作到下半部 (bottom half)。
现代中断子系统的核心抽象有三层:
- irq_chip: 硬件中断控制器 (IO-APIC, GIC 等)
- irq_domain: 硬件中断号 → Linux IRQ 号的映射
- irq_desc: 每个 Linux IRQ 的描述符 (handler, 统计, 亲和性)
硬件中断 vs Linux IRQ
硬件中断号 (hwirq):
中断控制器内部的中断线编号
不同控制器可以有相同的 hwirq
Linux IRQ 号 (virq):
内核统一的虚拟中断号
通过 irq_domain 映射: virq = irq_domain->map(hwirq)
/proc/interrupts 看到的就是 Linux IRQ 号
irq_desc
// include/linux/irqdesc.h
;
irqaction: 驱动注册的 handler
// include/linux/interrupt.h
;
中断处理流程
硬件到内核
handle_irq_desc() 路径
共享中断
IRQF_SHARED: 多个设备共享同一条中断线
→ 所有注册的 handler 依次调用
→ 每个 handler 检查"是不是我的设备产生的中断"
(读设备寄存器,如果不匹配 → 返回 IRQ_NONE)
→ 所有 handler 都返回 IRQ_NONE → 误触发 (spurious interrupt)
+ 记 spurious 计数 → 持续 100k 次 → 禁用此中断
下半部 (Bottom Half)
中断 handler 只做最紧急的事 (确认中断、屏蔽设备、复制数据)。耗时操作 (处理协议栈、回写缓存) 交给下半部。
softirq
// kernel/softirq.c
// 预定义的 softirq 类型 (编译时确定):
;
// softirq 运行在中断上下文中 (但开中断)
// 由 irq_exit() 触发检查:
// if (in_interrupt()) return; // 不在嵌套的硬件中断中
// do_softirq() → __do_softirq() → 遍历 softirq 位图
// ksoftirqd: per-CPU 内核线程
// 当 softirq 处理太多 (MAX_SOFTIRQ_RESTART) → 交给 ksoftirqd
// → 让出 CPU 给用户进程
tasklet (已废弃, 被 threaded IRQ 取代)
// kernel/softirq.c
// tasklet 基于 softirq (HI_SOFTIRQ 或 TASKLET_SOFTIRQ)
// 同类型的 tasklet 不会同时运行 (简化同步)
// ⚠️ 2022+ 内核中已废弃: 新代码使用 threaded IRQ
;
Threaded IRQ: 当前推荐方式
// kernel/irq/manage.c
// 每个中断可以有自己的内核线程
// handler 返回 IRQ_WAKE_THREAD → 内核调度 threaded_fn 运行
;
// handler: 在硬件中断上下文运行 (只做最小工作)
// thread_fn: 在独立内核线程中运行 (可以睡眠, 可以拿 mutex)
//
// 优点:
// - 减少中断关闭时间
// - 下半部可以睡眠 (拿 mutex, 做 IO)
// - 可以被实时调度策略管理
Workqueue: 更重的下半部
// kernel/workqueue.c
// workqueue 运行在进程上下文 (内核线程 kworker)
// 适合: 需要睡眠、需要长时间运行的工作
// 与 tasklet/softirq 的主要区别:
// workqueue: 进程上下文, 可以睡眠
// tasklet/softirq: 中断上下文, 不能睡眠
; // 系统 workqueue
; // 专用 workqueue
MSI / MSI-X
// kernel/irq/msi.c
// Message Signaled Interrupts
// 设备直接写内存地址 → 中断控制器 (不是走中断线)
// 优点:
// - 不需要共享 (每个 MSI 有唯一地址)
// - 更高性能 (PCIe posted write vs INTx 的缓慢电平信号)
// - MSI-X 允许设备有多个中断向量 (如 NVMe 每队列一个)
// PCI 设备启用 MSI:
;
→ 设备分配 16 个 MSI 向量
→ 返回 Linux IRQ
中断亲和性与负载均衡
# 查看中断分布
# 设置中断亲和性 (哪个 CPU 处理哪个中断)
# irqbalance 守护进程自动平衡
# 基于中断计数和 CPU 负载
# 某些中断 (如 NVMe) 直接绑定到 NUMA-local CPU
参考与延伸
- 内核文档:
Documentation/core-api/irq/,Documentation/PCI/msi-howto.rst - LWN: "The design of the interrupt subsystem", "Threaded interrupt handlers"
- 源码:
kernel/irq/— 中断核心 (handle, manage, chip, domain, msi)kernel/softirq.c— softirq 和 taskletkernel/workqueue.c— workqueuearch/x86/kernel/irq.c— x86 中断入口arch/x86/kernel/apic/— APIC 驱动
关键词: irq_desc, irq_chip, irq_domain, softirq, tasklet, threaded IRQ, workqueue, MSI/MSI-X, interrupt affinity