中断下半部、软中断与延后处理
这页讲的是:中断来了以后,为什么内核常常不会把所有工作都当场做完,而是先快速响应,再把后续工作拆到更合适的地方继续做。学这页的重点,是理解“事件来了”和“真正把活做完”之间,往往隔着一整层延后处理机制。
这块是什么
中断下半部、软中断与延后处理,讲的是当硬件事件打断系统后,内核如何把“必须立刻确认的事情”和“可以稍后继续做的事情”拆开处理。这样做不是绕弯,而是为了在及时响应和系统整体吞吐之间取得平衡。
可以把它理解成:门铃响了先去开门确认是谁,而不是站在门口把整顿饭都做完。真正的重活,通常会被安排到后面的更合适阶段。
它负责什么
把紧急响应做短
- 先快速确认事件确实发生
- 尽快清掉最紧急的硬件状态
- 减少对系统其余执行流的打断时间
- 避免中断上下文里停留太久
把重活往后挪
- 把大块数据处理延后
- 把更多协议或逻辑工作放到后续阶段
- 给系统留出更灵活的调度空间
- 减少“最敏感时刻做最重的活”
组织不同层次的后续处理
- 用软中断承接较快的后续工作
- 用更普通上下文承接更长的工作
- 让驱动、网络、存储路径能分层推进
- 让事件处理不是一刀切地只剩两种状态
为什么要拆成上半部和下半部
| 如果不拆 | 会怎样 | 拆开的价值 |
|---|
| 中断里直接做完全部工作 | 会占住很敏感的执行环境,拉高系统延迟。 | 把最急的事和最重的事分开,让系统更稳。 |
| 所有后续都统一一种处理方式 | 不是太重,就是太慢,难以兼顾不同路径需求。 | 可以按响应时效和上下文需求分层安排。 |
| 驱动自己随意决定延后逻辑 | 系统整体行为会更混乱,也更难理解性能问题。 | 内核提供相对稳定的延后处理世界观。 |
| 事件一来就长时间霸占 CPU | 别的任务和别的事件都会被拖慢。 | 拆分后更有利于全局吞吐和延迟平衡。 |
关键概念
| 概念 | 现在怎么理解 |
|---|
| 上半部 | 最先响应中断、应当尽量短小的那段处理。 |
| 下半部 | 把中断后续工作延后到更合适位置继续做的统称思路。 |
| 软中断 | 适合承接一类较快、较频繁后续处理的机制,网络等路径里很常见。 |
| tasklet | 历史上常被一起提到的延后处理方式,可先把它理解成下半部家族的一员。 |
| 延后处理 | 不是逃避工作,而是给工作换一个更合适的执行时机和上下文。 |
为什么重要
- 它解释了为什么“设备发来事件”不等于“所有后续立刻做完”。
- 很多网络和存储高吞吐路径,都是靠分层延后处理才能既快又不至于拖垮系统。
- 理解这层后,你会更容易看懂为什么中断、软中断、workqueue 常被连着讨论。
- 很多系统抖动、延迟和 CPU 忙碌感,根子都和这里的处理分工有关。
常见误解
- 误解一:延后处理就是拖延。实际上它是为了把工作放到更合适的上下文做。
- 误解二:中断越快做完越说明没后续。实际上很多成熟路径恰恰会故意把大量工作挪出去。
- 误解三:这只是驱动内部技巧。实际上它深刻影响网络、存储和系统整体延迟模型。
它不负责什么
- 它不定义设备语义或协议语义,而是组织事件后的处理路径。
- 它不替代 workqueue;两者经常连续出现,但适合的场景和上下文不同。
- 它不等于完整并发模型,但会直接影响同步方式和时序复杂度。
和其他模块的关系
| 相关模块 | 关系 |
|---|
| 中断与定时器 | 那页讲事件如何发生,这页更细讲事件来了之后如何继续推进。 |
| 并发控制 | 不同上下文能做什么、不能做什么,会直接影响锁和同步选择。 |
| 网络 / 存储 | 很多高吞吐路径都会把事件确认和重活处理拆开。 |
| workqueue | 当后续工作需要更普通的执行环境时,常继续转入 workqueue 等机制。 |
读完这页后,你应该能回答
- 为什么内核不喜欢在中断里把所有工作一次做完?
- 为什么“下半部”本质上是在重新安排工作时机和执行环境?
- 为什么软中断和 workqueue 往往会在同一条事件路径里先后出现?
后面适合继续问:网络收包为什么常和软中断一起被讨论?什么样的工作更适合再往后交给 workqueue?为什么延后处理会影响系统延迟体感?