Linux 软中断深度剖析: 从设计思想到实战调试
一、为什么需要软中断?——从生活比喻说起
想象一下繁忙的医院急诊科:
硬中断就像120急救车拉着警报冲到医院门口——情况紧急, 必须立即处理!医生需要马上评估患者生命体征, 进行最关键的抢救措施. 但这就够了吗?显然不够
软中断则像是护士接过病人后进行的后续处理: 详细登记信息、安排病房、准备长期治疗药物、联系家属等. 这些工作同样重要, 但可以在抢救稳定后稍后处理, 不必在救护车到达的瞬间全部完成
在Linux内核中, 硬中断(Hard IRQ)是硬件触发的立即响应, 而软中断(Software IRQ, softirq)则是延迟执行但优先级仍然很高的后台任务
硬中断 vs 软中断: 核心差异对比
| 触发源 | 硬件设备(网卡、磁盘、键盘) | 内核代码(通常在硬中断下半部) |
| 执行时机 | 异步, 立即响应 | 延迟但尽快执行 |
| 可抢占性 | 不可被其他硬中断抢占(同一CPU) | 可被硬中断抢占, 但不被其他软中断抢占 |
| 执行上下文 | 中断上下文(原子性) | 软中断上下文(仍是原子性, 但更宽松) |
| 调度方式 | 硬件触发, CPU直接跳转 | 内核主动检查并执行 |
| 并行性 | 同一IRQ号可能被屏蔽 | 可跨CPU并行执行(相同类型) |
| 典型应用 | 网卡收包通知, 键盘按键检测 | 网络协议栈处理, 块设备IO完成 |
二、软中断的核心设计思想
2.1 设计哲学: 中断处理的“分阶段”策略
Linux内核采用了著名的**“上半部/下半部”**(Top Half/Bottom Half)中断处理模型:
// 概念上的伪代码
void hardware_interrupt_handler(void)
{
/* 1. 上半部(硬中断上下文)*/
保存关键硬件状态();
标记"需要后续处理"();
触发软中断(); // 告诉内核: "稍后有重要工作要做"
/* 快速返回, 让硬件可以继续产生中断 */
}
// 稍后某个时刻(很快但非立即)
void softirq_handler(void)
{
/* 2. 下半部(软中断上下文)*/
处理网络数据包();
更新文件系统缓存();
调度任务();
// … 其他耗时但非紧急的工作
}
这种设计的核心动机在于:
- 缩短硬中断服务例程(ISR)的执行时间: 硬件中断必须快速响应, 长时间关闭中断会导致系统丢失中断事件
- 平衡实时性与吞吐量: 紧急操作立即执行, 繁重操作延迟但不无限期推迟
- 允许中断嵌套与重入: 软中断处理期间, 硬中断仍可正常响应
2.2 软中断的10种类型: 各司其职的内核工作者
Linux内核预定义了10种软中断类型, 每种都有专门用途:
// include/linux/interrupt.h
enum
{
HI_SOFTIRQ=0, // 高优先级tasklet
TIMER_SOFTIRQ, // 定时器回调
NET_TX_SOFTIRQ, // 网络数据包发送
NET_RX_SOFTIRQ, // 网络数据包接收
BLOCK_SOFTIRQ, // 块设备操作
IRQ_POLL_SOFTIRQ, // IRQ轮询
TASKLET_SOFTIRQ, // 普通tasklet
SCHED_SOFTIRQ, // 进程调度
HRTIMER_SOFTIRQ, // 高精度定时器
RCU_SOFTIRQ, // RCU回调
NR_SOFTIRQS // 软中断类型总数=10
};
三、核心数据结构深度解析
3.1 灵魂数据结构: softirq_vec 与 softnet_data
让我们深入内核源码, 看看软中断是如何组织的:
// kernel/softirq.c
/* 软中断描述符数组 – 系统的"软中断处理中心" */
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
struct softirq_action {
void (*action)(struct softirq_action *); // 处理函数指针
void *data; // 传递给处理函数的数据
};
/* 每个CPU的软中断状态控制块 */
DEFINE_PER_CPU(struct irq_cpustat_t, irq_stat);
/* 网络子系统专用的每CPU数据结构 */
struct softnet_data {
struct list_head poll_list; // NAPI轮询列表
struct sk_buff_head process_queue; // 待处理的数据包队列
// … 其他网络相关字段
};
3.2 数据结构关系图谱
#mermaid-svg-QMvE53uTrCWUtqpt{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QMvE53uTrCWUtqpt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QMvE53uTrCWUtqpt .error-icon{fill:#552222;}#mermaid-svg-QMvE53uTrCWUtqpt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QMvE53uTrCWUtqpt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QMvE53uTrCWUtqpt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QMvE53uTrCWUtqpt .marker.cross{stroke:#333333;}#mermaid-svg-QMvE53uTrCWUtqpt svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QMvE53uTrCWUtqpt p{margin:0;}#mermaid-svg-QMvE53uTrCWUtqpt .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-QMvE53uTrCWUtqpt .cluster-label text{fill:#333;}#mermaid-svg-QMvE53uTrCWUtqpt .cluster-label span{color:#333;}#mermaid-svg-QMvE53uTrCWUtqpt .cluster-label span p{background-color:transparent;}#mermaid-svg-QMvE53uTrCWUtqpt .label text,#mermaid-svg-QMvE53uTrCWUtqpt span{fill:#333;color:#333;}#mermaid-svg-QMvE53uTrCWUtqpt .node rect,#mermaid-svg-QMvE53uTrCWUtqpt .node circle,#mermaid-svg-QMvE53uTrCWUtqpt .node ellipse,#mermaid-svg-QMvE53uTrCWUtqpt .node polygon,#mermaid-svg-QMvE53uTrCWUtqpt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QMvE53uTrCWUtqpt .rough-node .label text,#mermaid-svg-QMvE53uTrCWUtqpt .node .label text,#mermaid-svg-QMvE53uTrCWUtqpt .image-shape .label,#mermaid-svg-QMvE53uTrCWUtqpt .icon-shape .label{text-anchor:middle;}#mermaid-svg-QMvE53uTrCWUtqpt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QMvE53uTrCWUtqpt .rough-node .label,#mermaid-svg-QMvE53uTrCWUtqpt .node .label,#mermaid-svg-QMvE53uTrCWUtqpt .image-shape .label,#mermaid-svg-QMvE53uTrCWUtqpt .icon-shape .label{text-align:center;}#mermaid-svg-QMvE53uTrCWUtqpt .node.clickable{cursor:pointer;}#mermaid-svg-QMvE53uTrCWUtqpt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QMvE53uTrCWUtqpt .arrowheadPath{fill:#333333;}#mermaid-svg-QMvE53uTrCWUtqpt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QMvE53uTrCWUtqpt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QMvE53uTrCWUtqpt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QMvE53uTrCWUtqpt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QMvE53uTrCWUtqpt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QMvE53uTrCWUtqpt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QMvE53uTrCWUtqpt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QMvE53uTrCWUtqpt .cluster text{fill:#333;}#mermaid-svg-QMvE53uTrCWUtqpt .cluster span{color:#333;}#mermaid-svg-QMvE53uTrCWUtqpt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QMvE53uTrCWUtqpt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QMvE53uTrCWUtqpt rect.text{fill:none;stroke-width:0;}#mermaid-svg-QMvE53uTrCWUtqpt .icon-shape,#mermaid-svg-QMvE53uTrCWUtqpt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QMvE53uTrCWUtqpt .icon-shape p,#mermaid-svg-QMvE53uTrCWUtqpt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QMvE53uTrCWUtqpt .icon-shape rect,#mermaid-svg-QMvE53uTrCWUtqpt .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QMvE53uTrCWUtqpt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QMvE53uTrCWUtqpt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QMvE53uTrCWUtqpt :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
全局软中断向量表
Per-CPU 数据结构
网络接收处理
网络接收处理
__softirq_pending位图
__softirq_pending位图
CPU 0
irq_cpustat_t
softnet_data
CPU 1
irq_cpustat_t
softnet_data
softirq_vec数组
softirq_action 0: HI_SOFTIRQ
softirq_action 1: TIMER_SOFTIRQ
softirq_action 2: NET_TX_SOFTIRQ
softirq_action 3: NET_RX_SOFTIRQ
softirq_action 9: RCU_SOFTIRQ
3.3 关键位图: __softirq_pending
每个CPU都有一个__softirq_pending位图, 这是软中断系统的**“待办事项清单”**:
// arch/x86/include/asm/hardirq.h
typedef struct {
unsigned int __softirq_pending; // 位图: 哪类软中断需要处理?
unsigned int ipi_irqs[NR_IPI]; // 处理器间中断计数
} ____cacheline_aligned irq_cpustat_t;
这个32位整数的每一位对应一种软中断类型:
- 位0(1 << 0): HI_SOFTIRQ待处理
- 位3(1 << 3): NET_RX_SOFTIRQ待处理
- …
当硬件中断处理程序需要调度一个软中断时, 就设置对应的位, 相当于在"待办清单"上打个勾
四、软中断的生命周期: 触发、执行与调度
4.1 触发软中断: 设置"待办事项"
// 触发软中断的核心函数
void raise_softirq(unsigned int nr) // nr是软中断类型号
{
unsigned long flags;
local_irq_save(flags); // 保存中断状态并禁用本地中断
raise_softirq_irqoff(nr); // 实际设置位图
local_irq_restore(flags); // 恢复中断状态
}
static inline void raise_softirq_irqoff(unsigned int nr)
{
__raise_softirq_irqoff(nr); // 设置当前CPU的__softirq_pending位
/*
* 特殊情况处理:
* 1. 如果在中断上下文中, 什么也不做(后续会自然处理)
* 2. 如果在进程上下文中, 唤醒ksoftirqd线程
*/
if (!in_interrupt())
wakeup_softirqd(); // 唤醒软中断守护线程
}
4.2 执行软中断: 处理"待办事项"
软中断的执行入口在do_softirq()函数中:
// kernel/softirq.c (简化版本)
asmlinkage __visible void do_softirq(void)
{
unsigned long pending;
unsigned long flags;
/* 1. 检查是否在正确上下文 */
if (in_interrupt()) return;
/* 2. 禁用本地中断, 获取待处理位图 */
local_irq_save(flags);
pending = local_softirq_pending();
/* 3. 如果有待处理的软中断 */
if (pending) {
/* 设置正在处理软中断的标志 */
__do_softirq();
}
/* 4. 恢复中断状态 */
local_irq_restore(flags);
}
真正的处理在__do_softirq()中:
#mermaid-svg-tnc5uMDwQPMMuVH9{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tnc5uMDwQPMMuVH9 .error-icon{fill:#552222;}#mermaid-svg-tnc5uMDwQPMMuVH9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tnc5uMDwQPMMuVH9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .marker.cross{stroke:#333333;}#mermaid-svg-tnc5uMDwQPMMuVH9 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tnc5uMDwQPMMuVH9 p{margin:0;}#mermaid-svg-tnc5uMDwQPMMuVH9 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .cluster-label text{fill:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .cluster-label span{color:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .cluster-label span p{background-color:transparent;}#mermaid-svg-tnc5uMDwQPMMuVH9 .label text,#mermaid-svg-tnc5uMDwQPMMuVH9 span{fill:#333;color:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .node rect,#mermaid-svg-tnc5uMDwQPMMuVH9 .node circle,#mermaid-svg-tnc5uMDwQPMMuVH9 .node ellipse,#mermaid-svg-tnc5uMDwQPMMuVH9 .node polygon,#mermaid-svg-tnc5uMDwQPMMuVH9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .rough-node .label text,#mermaid-svg-tnc5uMDwQPMMuVH9 .node .label text,#mermaid-svg-tnc5uMDwQPMMuVH9 .image-shape .label,#mermaid-svg-tnc5uMDwQPMMuVH9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-tnc5uMDwQPMMuVH9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .rough-node .label,#mermaid-svg-tnc5uMDwQPMMuVH9 .node .label,#mermaid-svg-tnc5uMDwQPMMuVH9 .image-shape .label,#mermaid-svg-tnc5uMDwQPMMuVH9 .icon-shape .label{text-align:center;}#mermaid-svg-tnc5uMDwQPMMuVH9 .node.clickable{cursor:pointer;}#mermaid-svg-tnc5uMDwQPMMuVH9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .arrowheadPath{fill:#333333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tnc5uMDwQPMMuVH9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tnc5uMDwQPMMuVH9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tnc5uMDwQPMMuVH9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tnc5uMDwQPMMuVH9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .cluster text{fill:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 .cluster span{color:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tnc5uMDwQPMMuVH9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tnc5uMDwQPMMuVH9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-tnc5uMDwQPMMuVH9 .icon-shape,#mermaid-svg-tnc5uMDwQPMMuVH9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tnc5uMDwQPMMuVH9 .icon-shape p,#mermaid-svg-tnc5uMDwQPMMuVH9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tnc5uMDwQPMMuVH9 .icon-shape rect,#mermaid-svg-tnc5uMDwQPMMuVH9 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tnc5uMDwQPMMuVH9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tnc5uMDwQPMMuVH9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tnc5uMDwQPMMuVH9 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
否
是
否
是
否
是
__do_softirq开始
获取pending位图\\npending = local_softirq_pending
pending == 0?
直接返回
设置in_softirq标志
清除pending位图\\nlocal_softirq_pending = 0
恢复本地中断\\n允许硬中断嵌套
循环: i从0到NR_SOFTIRQS
pending & 1 << i ?
下一个i
执行softirq_vec[i].action
增加已处理计数
所有位检查完毕?
重新获取pending\\n检查新到达的软中断
处理超过最大限制\\n或需要调度?
唤醒ksoftirqd线程
清除in_softirq标志
__do_softirq结束
4.3 执行时机的"四大检查点"
软中断不会立即执行, 而是在特定检查点被处理:
// 从硬中断返回时的处理路径
irq_exit():
if (!in_interrupt() && local_softirq_pending())
invoke_softirq() —> do_softirq()
五、实战案例: 网络数据包接收的完整旅程
让我们追踪一个网络数据包如何通过软中断被处理:
5.1 数据包接收的完整流程
用户空间应用协议栈处理软中断处理硬中断处理网卡硬件用户空间应用协议栈处理软中断处理硬中断处理网卡硬件#mermaid-svg-Ozii9jyGjGbvsyzJ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ozii9jyGjGbvsyzJ .error-icon{fill:#552222;}#mermaid-svg-Ozii9jyGjGbvsyzJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ozii9jyGjGbvsyzJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ozii9jyGjGbvsyzJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ozii9jyGjGbvsyzJ .marker.cross{stroke:#333333;}#mermaid-svg-Ozii9jyGjGbvsyzJ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ozii9jyGjGbvsyzJ p{margin:0;}#mermaid-svg-Ozii9jyGjGbvsyzJ .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ozii9jyGjGbvsyzJ text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Ozii9jyGjGbvsyzJ .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Ozii9jyGjGbvsyzJ .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Ozii9jyGjGbvsyzJ #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Ozii9jyGjGbvsyzJ .sequenceNumber{fill:white;}#mermaid-svg-Ozii9jyGjGbvsyzJ #sequencenumber{fill:#333;}#mermaid-svg-Ozii9jyGjGbvsyzJ #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Ozii9jyGjGbvsyzJ .messageText{fill:#333;stroke:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ozii9jyGjGbvsyzJ .labelText,#mermaid-svg-Ozii9jyGjGbvsyzJ .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .loopText,#mermaid-svg-Ozii9jyGjGbvsyzJ .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Ozii9jyGjGbvsyzJ .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Ozii9jyGjGbvsyzJ .noteText,#mermaid-svg-Ozii9jyGjGbvsyzJ .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Ozii9jyGjGbvsyzJ .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ozii9jyGjGbvsyzJ .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ozii9jyGjGbvsyzJ .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ozii9jyGjGbvsyzJ .actorPopupMenu{position:absolute;}#mermaid-svg-Ozii9jyGjGbvsyzJ .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Ozii9jyGjGbvsyzJ .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ozii9jyGjGbvsyzJ .actor-man circle,#mermaid-svg-Ozii9jyGjGbvsyzJ line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Ozii9jyGjGbvsyzJ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}稍后(微秒级延迟)1. 数据包到达, 触发硬中断2. 禁用进一步中断 读取描述符3. 设置NET_RX_SOFTIRQ位4. 重新启用中断5. 快速返回6. do_softirq()执行7. net_rx_action()处理8. 协议解析(IP/TCP)9. 放入socket接收缓冲区10. read()系统调用读取
5.2 核心代码片段分析
// 网络设备驱动中的典型硬中断处理
irqreturn_t network_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
/* 1. 确认中断来自我们的设备 */
if (!check_interrupt_source(dev))
return IRQ_NONE;
/* 2. 禁用设备的进一步中断(可选) */
disable_device_interrupts(dev);
/* 3. 调度软中断进行后续处理 */
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
/* 4. 快速返回 – 这是硬中断的关键! */
return IRQ_HANDLED;
}
// NET_RX_SOFTIRQ对应的处理函数
static void net_rx_action(struct softirq_action *h)
{
struct softnet_data *sd = this_cpu_ptr(&softnet_data);
unsigned long time_limit = jiffies + 2; // 最多运行2个jiffies
int budget = 300; // 最多处理300个数据包
/* 处理接收队列中的数据包 */
while (!list_empty(&sd->poll_list)) {
struct napi_struct *n = list_first_entry(&sd->poll_list);
/* 执行NAPI轮询 */
int work = n->poll(n, budget);
/* 更新已处理的预算 */
budget -= work;
/* 检查限制条件: 时间或预算耗尽 */
if (budget <= 0 || time_after(jiffies, time_limit)) {
/* 如果还有工作, 重新调度自己 */
if (!list_empty(&sd->poll_list))
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
break;
}
}
}
六、软中断的并发与性能考虑
6.1 每CPU变量: 性能的关键设计
软中断最巧妙的设计之一是每CPU变量(per-cpu variables):
// 每个CPU有自己独立的软中断状态
static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
// 这意味着:
// – CPU0设置自己的__softirq_pending位图
// – CPU1设置自己的__softirq_pending位图
// – 互不干扰, 无需加锁!
这种设计带来两大好处:
6.2 软中断的并行执行模型
#mermaid-svg-VWhh6vSOZofS81WX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VWhh6vSOZofS81WX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VWhh6vSOZofS81WX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VWhh6vSOZofS81WX .error-icon{fill:#552222;}#mermaid-svg-VWhh6vSOZofS81WX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VWhh6vSOZofS81WX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VWhh6vSOZofS81WX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VWhh6vSOZofS81WX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VWhh6vSOZofS81WX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VWhh6vSOZofS81WX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VWhh6vSOZofS81WX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VWhh6vSOZofS81WX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VWhh6vSOZofS81WX .marker.cross{stroke:#333333;}#mermaid-svg-VWhh6vSOZofS81WX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VWhh6vSOZofS81WX p{margin:0;}#mermaid-svg-VWhh6vSOZofS81WX .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-VWhh6vSOZofS81WX .cluster-label text{fill:#333;}#mermaid-svg-VWhh6vSOZofS81WX .cluster-label span{color:#333;}#mermaid-svg-VWhh6vSOZofS81WX .cluster-label span p{background-color:transparent;}#mermaid-svg-VWhh6vSOZofS81WX .label text,#mermaid-svg-VWhh6vSOZofS81WX span{fill:#333;color:#333;}#mermaid-svg-VWhh6vSOZofS81WX .node rect,#mermaid-svg-VWhh6vSOZofS81WX .node circle,#mermaid-svg-VWhh6vSOZofS81WX .node ellipse,#mermaid-svg-VWhh6vSOZofS81WX .node polygon,#mermaid-svg-VWhh6vSOZofS81WX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VWhh6vSOZofS81WX .rough-node .label text,#mermaid-svg-VWhh6vSOZofS81WX .node .label text,#mermaid-svg-VWhh6vSOZofS81WX .image-shape .label,#mermaid-svg-VWhh6vSOZofS81WX .icon-shape .label{text-anchor:middle;}#mermaid-svg-VWhh6vSOZofS81WX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VWhh6vSOZofS81WX .rough-node .label,#mermaid-svg-VWhh6vSOZofS81WX .node .label,#mermaid-svg-VWhh6vSOZofS81WX .image-shape .label,#mermaid-svg-VWhh6vSOZofS81WX .icon-shape .label{text-align:center;}#mermaid-svg-VWhh6vSOZofS81WX .node.clickable{cursor:pointer;}#mermaid-svg-VWhh6vSOZofS81WX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VWhh6vSOZofS81WX .arrowheadPath{fill:#333333;}#mermaid-svg-VWhh6vSOZofS81WX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VWhh6vSOZofS81WX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VWhh6vSOZofS81WX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VWhh6vSOZofS81WX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VWhh6vSOZofS81WX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VWhh6vSOZofS81WX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VWhh6vSOZofS81WX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VWhh6vSOZofS81WX .cluster text{fill:#333;}#mermaid-svg-VWhh6vSOZofS81WX .cluster span{color:#333;}#mermaid-svg-VWhh6vSOZofS81WX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VWhh6vSOZofS81WX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VWhh6vSOZofS81WX rect.text{fill:none;stroke-width:0;}#mermaid-svg-VWhh6vSOZofS81WX .icon-shape,#mermaid-svg-VWhh6vSOZofS81WX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VWhh6vSOZofS81WX .icon-shape p,#mermaid-svg-VWhh6vSOZofS81WX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VWhh6vSOZofS81WX .icon-shape rect,#mermaid-svg-VWhh6vSOZofS81WX .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VWhh6vSOZofS81WX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VWhh6vSOZofS81WX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VWhh6vSOZofS81WX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
CPU 1
CPU 0
硬中断0
设置软中断位
do_softirq
执行NET_RX
ksoftirqd/0
辅助处理
硬中断1
设置软中断位
do_softirq
执行NET_RX
ksoftirqd/1
辅助处理
共享数据结构 需要同步
关键规则:
- 相同类型的软中断可以在不同CPU上同时运行
- 同一CPU上, 软中断不会被其他软中断抢占(但会被硬中断抢占)
- 如果软中断处理函数被重入, 可能引发死锁, 需要仔细设计
七、软中断的监控与调试实战
7.1 监控工具大全
| /proc/softirqs | 查看软中断统计 | cat /proc/softirqs |
| /proc/interrupts | 查看硬中断统计 | cat /proc/interrupts |
| watch | 实时监控 | watch -n1 'cat /proc/softirqs' |
| mpstat -P ALL 1 | CPU使用情况 | 观察%soft列 |
| top | 系统概览 | 观察si(软中断)CPU时间 |
| perf | 性能分析 | perf record -a -g sleep 10 |
| trace-cmd | 跟踪事件 | trace-cmd record -e irq:* |
| ftrace | 内核跟踪 | echo 1 > /sys/kernel/debug/tracing/events/irq/enable |
7.2 实战调试: 软中断占用过高问题排查
# 1. 快速检查软中断分布
$ watch -n1 "cat /proc/softirqs | awk 'NR==1{print} \\$1~/NET/||NR<=3{print}'"
CPU0 CPU1 CPU2 CPU3
HI: 1 0 0 0
TIMER: 12345678 23456789 34567890 45678901
NET_RX: 98765432 87654321 76543210 65432109 # <– 网络接收软中断异常高!
NET_TX: 1234 5678 9012 3456
# 2. 确认是哪个网络设备的问题
$ cat /proc/interrupts | grep eth
66: 12345678 IO-APIC-edge eth0-rx-0
67: 8765432 IO-APIC-edge eth0-tx-0
68: 98765432 IO-APIC-edge eth0-rx-1 # <– eth0的第二个接收队列中断很高
# 3. 使用perf进行性能分析
$ perf top -C 0 # 查看CPU0上什么函数消耗最多时间
47.32% [kernel] [k] net_rx_action # 网络接收软中断处理
12.45% [kernel] [k] __napi_poll
8.76% [kernel] [k] ip_rcv
# 4. 调整优化(如果确定是网络负载高)
# 启用RSS(接收侧扩展)分散到多个CPU
$ ethtool -L eth0 combined 4
# 调整软中断处理预算
$ sysctl -w net.core.netdev_budget=600
7.3 常见问题与解决方案
| 软中断CPU使用率持续>30% | 网络包洪水攻击 | 启用防火墙, 调整网络队列 |
| 单CPU软中断过高 | 中断亲和性设置不当 | 设置irqbalance或手动调整IRQ affinity |
| 网络延迟高 | 软中断处理不及时 | 增加netdev_budget, 优化驱动 |
| 软中断处理函数卡住 | 函数内部死锁或bug | 使用ftrace跟踪, 检查内核日志 |
八、软中断的演进: 从softirq到threaded IRQ
8.1 线程化中断: 现代内核的选择
虽然软中断性能很高, 但它在中断上下文中运行, 导致:
- 不能睡眠(不能调用可能阻塞的函数)
- 调试困难(难以跟踪)
- 实时性影响(长时间运行会延迟其他任务)
Linux 2.6.30+引入了线程化中断:
// 请求一个线程化中断
request_threaded_irq(irq, hardware_handler, thread_handler, flags, name, dev);
// hardware_handler: 在硬中断上下文中快速执行
// thread_handler: 在专用的内核线程中执行(可以睡眠!)
8.2 三种下半部机制对比
| 执行上下文 | 软中断上下文 | 软中断上下文 | 进程上下文 |
| 可睡眠 | 否 | 否 | 是 |
| 并行性 | 可跨CPU并行 | 同类型不能跨CPU并行 | 可跨CPU并行 |
| 延迟 | 低(微秒级) | 低(微秒级) | 较高(可能被调度延迟) |
| 使用场景 | 网络、块设备等高吞吐 | 驱动中的中小型任务 | 需要睡眠的复杂任务 |
| 预定义类型 | 10种固定类型 | 动态创建 | 动态创建 |
| 实现复杂度 | 高 | 中 | 低 |
九、编写自定义软中断: 简单示例
虽然大多数情况下使用预定义的软中断, 但了解如何注册自定义软中断很有教育意义:
// 示例: 自定义软中断模块
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#define MY_SOFTIRQ 10 // 危险!可能冲突, 仅用于演示
static void my_softirq_handler(struct softirq_action *h)
{
printk(KERN_INFO "My softirq handler running on CPU %d\\n", smp_processor_id());
}
static int __init my_softirq_init(void)
{
// 注册自定义软中断(实际中不建议, 可能破坏系统)
// open_softirq(MY_SOFTIRQ, my_softirq_handler);
// 更安全的做法: 使用tasklet
DECLARE_TASKLET(my_tasklet, my_tasklet_handler, 0);
printk(KERN_INFO "SoftIRQ demo module loaded\\n");
// 触发一个tasklet
tasklet_schedule(&my_tasklet);
return 0;
}
static void my_tasklet_handler(unsigned long data)
{
printk(KERN_INFO "Tasklet running on CPU %d\\n", smp_processor_id());
}
static void __exit my_softirq_exit(void)
{
printk(KERN_INFO "SoftIRQ demo module unloaded\\n");
}
module_init(my_softirq_init);
module_exit(my_softirq_exit);
MODULE_LICENSE("GPL");
十、总结: 软中断的设计智慧
10.1 核心要点回顾
通过本文的深入分析, 我们可以总结软中断的核心设计智慧:
10.2 软中断在Linux内核中的地位
#mermaid-svg-o4iCszPirbjsTUGf{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-o4iCszPirbjsTUGf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-o4iCszPirbjsTUGf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-o4iCszPirbjsTUGf .error-icon{fill:#552222;}#mermaid-svg-o4iCszPirbjsTUGf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-o4iCszPirbjsTUGf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-o4iCszPirbjsTUGf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-o4iCszPirbjsTUGf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-o4iCszPirbjsTUGf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-o4iCszPirbjsTUGf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-o4iCszPirbjsTUGf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-o4iCszPirbjsTUGf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-o4iCszPirbjsTUGf .marker.cross{stroke:#333333;}#mermaid-svg-o4iCszPirbjsTUGf svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-o4iCszPirbjsTUGf p{margin:0;}#mermaid-svg-o4iCszPirbjsTUGf .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-o4iCszPirbjsTUGf .cluster-label text{fill:#333;}#mermaid-svg-o4iCszPirbjsTUGf .cluster-label span{color:#333;}#mermaid-svg-o4iCszPirbjsTUGf .cluster-label span p{background-color:transparent;}#mermaid-svg-o4iCszPirbjsTUGf .label text,#mermaid-svg-o4iCszPirbjsTUGf span{fill:#333;color:#333;}#mermaid-svg-o4iCszPirbjsTUGf .node rect,#mermaid-svg-o4iCszPirbjsTUGf .node circle,#mermaid-svg-o4iCszPirbjsTUGf .node ellipse,#mermaid-svg-o4iCszPirbjsTUGf .node polygon,#mermaid-svg-o4iCszPirbjsTUGf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-o4iCszPirbjsTUGf .rough-node .label text,#mermaid-svg-o4iCszPirbjsTUGf .node .label text,#mermaid-svg-o4iCszPirbjsTUGf .image-shape .label,#mermaid-svg-o4iCszPirbjsTUGf .icon-shape .label{text-anchor:middle;}#mermaid-svg-o4iCszPirbjsTUGf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-o4iCszPirbjsTUGf .rough-node .label,#mermaid-svg-o4iCszPirbjsTUGf .node .label,#mermaid-svg-o4iCszPirbjsTUGf .image-shape .label,#mermaid-svg-o4iCszPirbjsTUGf .icon-shape .label{text-align:center;}#mermaid-svg-o4iCszPirbjsTUGf .node.clickable{cursor:pointer;}#mermaid-svg-o4iCszPirbjsTUGf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-o4iCszPirbjsTUGf .arrowheadPath{fill:#333333;}#mermaid-svg-o4iCszPirbjsTUGf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-o4iCszPirbjsTUGf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-o4iCszPirbjsTUGf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o4iCszPirbjsTUGf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-o4iCszPirbjsTUGf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o4iCszPirbjsTUGf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-o4iCszPirbjsTUGf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-o4iCszPirbjsTUGf .cluster text{fill:#333;}#mermaid-svg-o4iCszPirbjsTUGf .cluster span{color:#333;}#mermaid-svg-o4iCszPirbjsTUGf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-o4iCszPirbjsTUGf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-o4iCszPirbjsTUGf rect.text{fill:none;stroke-width:0;}#mermaid-svg-o4iCszPirbjsTUGf .icon-shape,#mermaid-svg-o4iCszPirbjsTUGf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o4iCszPirbjsTUGf .icon-shape p,#mermaid-svg-o4iCszPirbjsTUGf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-o4iCszPirbjsTUGf .icon-shape rect,#mermaid-svg-o4iCszPirbjsTUGf .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o4iCszPirbjsTUGf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-o4iCszPirbjsTUGf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-o4iCszPirbjsTUGf :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
硬件中断
中断处理模型选择
性能敏感且无需睡眠
使用软中断/Tasklet 如网络、块设备
需要睡眠或复杂操作
使用工作队列 如文件系统、设备探测
实时性要求高
使用线程化中断 如音频、工业控制
高吞吐 低延迟
功能强大 易于编程
可抢占 易调试

