大家好,我是王鸽,今天这篇文章主要是讲解中断嵌套的介绍,以及中断嵌套使用过程的注意点。中断嵌套
Linux下硬中断是可以嵌套的,任何一个新的中断都可以打断正在执行的中断,但同种中断除外。硬中断处理函数必须极致轻量化,软中断/tasklet/workqueue 不会参与嵌套,但相同类型的软中断可以在不同CPU上并行执行。
讲中断嵌套之前先了解一下几个概念,中断优先级,中断屏蔽。
中断优先级
Linux 为每个中断(IRQ)分配了优先级(数值越小,优先级越高),优先级由硬件中断控制器(如 ARM GIC、x86 IOAPIC)和内核配置共同决定。中断屏蔽
CPU 有一个 “中断屏蔽位”(CPSR 寄存器的 I 位 / ARM、EFLAGS 的 IF 位 /x86),置位时会屏蔽所有可屏蔽中断,清零时响应中断。1. 中断嵌套的核心规则
比如网卡中断(高优先级)可以打断 UART 中断(低优先级);
同一个中断控制器(如 GIC)下,相同优先级的中断会被阻塞,直到当前中断处理完成;
软中断优先级低于所有硬中断,硬中断可以抢占软中断,但软中断永远抢不了硬中断;
软中断执行时,新的软中断会被延迟到当前软中断执行完再处理(除非被硬中断抢占后重新触发)。
2.硬中断上下文的限制
嵌套发生在硬件中断(hardirq)上下文,软中断 /tasklet 不会嵌套(软中断在硬中断处理完后执行,且同类型软中断不会重入)。3.内核的 “中断抢占” 开关
Linux 内核有一个配置项CONFIG_PREEMPT_IRQ,开启后才允许完全的中断嵌套;关闭时,硬中断处理过程中不会被其他硬中断抢占(仅能在硬中断处理间隙响应高优先级中断)。
中断嵌套的典型场景(举例)
场景:网卡中断(高优先级)嵌套UART中断(低优先级) 1. CPU执行UART硬中断处理函数(低优先级)2. 网卡产生硬中断(高优先级)→ GIC判定优先级更高 → 暂停UART中断3. 执行网卡硬中断处理函数(清中断、触发NET_RX软中断)4. 网卡硬中断执行完 → 回到UART硬中断继续执行 5. UART硬中断执行完 → 触发软中断处理(网卡数据+UART数
在比如低优先级中断IRQ10和高优先级中断IRQ5。嵌套的风险与避坑
嵌套过深
会导致中断栈溢出(Linux 中断栈大小固定,一般 8K/16K),驱动中要避免硬中断处理函数过长;系统响应延迟(低优先级中断长时间得不到处理)。内核默认会限制嵌套层数(如 ARM 架构默认最大嵌套 8 层)。
死锁
如果硬中断 A 嵌套硬中断 B,且 A、B 都抢同一个自旋锁,会导致死锁(自旋锁在中断上下文必须用spin_lock_irqsave);
禁止在硬中断中用local_irq_disable()太久
会导致高优先级中断也被屏蔽,引发网卡丢包、定时器不准等问题。
中断处理函数的要求
- 不能阻塞 / 睡眠(中断上下文无进程调度,睡眠会导致系统卡死);
查看中断优先级(ARM GIC)
cat/proc/interrupts //基础的中断信息cat/sys/kernel/irq/<irq_num>/priority //查看指定 IRQ 优先级(需内核支持)谢谢点赞阅读收藏!