37 中断如何在不变中演变
# 37 中断如何在不变中演变
Linux 始终分两个阶段处理中断:立即运行的快速上半部分,以及完成剩余工作的延迟下半部分。尽管这一模型从最早的内核起就保持一致,但其背后的机制已发生显著演变。
在 Linux 1.x 和 2.0 中,下半部分实现为全局静态处理程序列表。即使在多处理器系统上,一次也只能运行一个,这种序列化设计随着对称多处理的普及成为可扩展性瓶颈。
为解决这一问题,Linux 2.3 引入软中断(softirqs),这是一种在中断上下文中处理延迟工作的 per-CPU 机制。软中断对网络、定时器和 RCU 仍至关重要,但其不能睡眠或被抢占,在负载下可能导致延迟。为简化使用,任务小项(tasklets)作为更高层接口被添加,管理序列化并抽象软中断细节,但保留了相同的原子约束。随着工作负载变得更复杂,这种灵活性的缺乏开始受限。
Linux 2.5 引入工作队列(workqueues),允许延迟工作完全在线程上下文中运行。工作队列处理程序可以睡眠、阻塞,并像任何其他内核线程一样与调度器交互。如今,工作队列是通用延迟处理的标准机制,已取代任务小项和自定义线程逻辑的大部分用途。
一个重大转变是线程化中断处理程序的引入,最初在 PREEMPT_RT 补丁集中开发,并在 Linux 2.6.30 中合并到主线。在这种模型中,上半部分仅确认中断,唤醒专用内核线程处理其余部分。这些处理程序可以睡眠、按优先级调度,并且完全可抢占,非常适合实时或对延迟敏感的工作负载。现在许多驱动程序默认使用线程化 IRQ。
从 Linux 2.6 到 4.x,内核通过 blk-mq、RPS 和 RFS 等功能改进中断处理,同时合并关键的 PREEMPT_RT 增强功能。这些更改提高了可扩展性和响应性,而不改变快速上半部分执行和延迟下半部分工作的核心模型。
Linux 6.x 继续这一进程。NAPI(网络轮询机制)现在可以在专用线程而非软中断上下文中运行,这改善了调度控制和 CPU 隔离,尤其在有严格性能或延迟约束的系统中。
曾经是软中断便捷抽象的任务小项现在已弃用,其序列化、原子执行不再与内核向灵活的基于线程的基础设施的转变一致。仍依赖它们的子系统正在迁移到工作队列或线程化 IRQ。
在此过程中,中断模型始终不变:处理紧急事务,延迟其余部分。改变的是延迟处理的实现方式——从序列化、不可抢占的路径转向并发、可调度的执行。接口保持不变,只是内核更擅长实现它。