Linux的中断可以嵌套吗?

本文探讨了Linux内核中断机制的历史发展,特别是在2010年后中断嵌套的支持被取消的情况。原先存在快中断和慢中断的区别,前者在处理时屏蔽新中断,后者则允许中断嵌套。随着中断嵌套风险的增加,现代Linux内核统一不再支持中断嵌套。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问答

问:Linux的中断可以嵌套吗?

答:以前是可以嵌套的,现在不可以!

历史

早前的Linux内核版本,中断分为两种:

  1. 快中断,申请的时候带IRQF_DISABLED标记,在IRQ HANDLER里面不允许新的中断进来;

  2. 慢中断,申请的时候不带IRQF_DISABLED标记,在IRQ HANDLER里面允许新的其他中断嵌套进来。

老的Linux内核中,如果一个中断服务程序不想被别的中断打断,我们能看到这样的代码:

request_irq(FLOPPY_IRQ, floppy_interrupt,\
-					    IRQF_DISABLED, "floppy", NULL)

现在

在2010年如下的commit中,IRQF_DISABLED被作废了:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e58aa3d2d0cc

640?wx_fmt=png

它的commit log清晰地解释中断嵌套可能引入的一些risk,比如stack溢出等。也就是说,从这个commit开始,实际Linux已经不再支持中断的嵌套, 也没有快慢中断的概念了,IRQF_DISABLED标记也作废了。在IRQ HANDLER里面,无论一个中断设置还是不设置IRQF_DISABLED, 内核都不会开启CPU对中断的响应:

640?wx_fmt=png

这个作废的IRQF_DISABLED标记,在内核已经没有任何的意义了。后来,这个标记本身,在内核里面也被删除了,彻底成为过往:

640?wx_fmt=png

硬件

中断发生后,一般硬件会自动屏蔽CPU对中断的响应,而软件层面上,直到IRQ HANDLER做完,才会重新开启中断。比如,对于ARM处理器而言,exception进来的时候,硬件都会自动屏蔽中断:

640?wx_fmt=png

也就是说,当ARM处理器收到中断的时候,它进入中断模式,同时ARM处理器的CPSR寄存器的IRQ位会被硬件设置为屏蔽IRQ。


Linux内核会在如下2个时候重新开启CPSR对IRQ的响应:

  1. 从IRQ HANDLER返回中断底半部的SOFTIRQ

  2. 从IRQ HANDLER返回一个线程上下文


从1大家可以看出,SOFTIRQ里面是可以响应中断的。

(完)


"Linux阅码场"是专业的Linux及系统软件技术交流社区,Linux系统人才培养基地,企业和Linux人才的连接枢纽。


查看我们精华技术文章请移步:

Linux阅码场精华文章汇总


求职招聘请移步:

Linux阅码场: 连接企业和Linux人才的platform总线


扫描二维码关注我们 

640?wx_fmt=png

如果觉得好,请

转发

转发

转发

<think>我们正在讨论Linux内核中软中断的执行机制,特别是软中断之间是否可以互相打断。根据引用内容,我们可以总结以下关键点:1.软中断(softirq)是中断处理程序的下半部(bottomhalf),在开启中断的情况下执行(引用[1][5])。2.软中断可以被硬中断抢占(引用[1])。3.内核不会立即处理重新触发的软中断。当大量软中断出现时,内核会唤醒一组内核线程(ksoftirqd)来处理,这些线程的优先级最低(nice值为19),以避免与重要任务抢夺资源(引用[2])。4.软中断包括硬件设备中断处理程序的下半部,也包括内核自定义的事件(如调度和RCU锁)(引用[3])。5.软中断处理函数通过`open_softirq`注册(引用[4])。关于软中断之间是否可以互相打断:-软中断在执行时,是开启中断的,因此可以被硬中断打断(引用[1])。-但是,软中断在执行过程中是否会被另一个软中断打断呢?根据Linux内核的设计,软中断的执行机制如下:-软中断中断上下文中执行(由硬件中断触发)或者在内核线程ksoftirqd中执行(当软中断过多时)。-在中断上下文中执行软中断时,内核处于中断处理的软中断阶段(即`do_softirq()`函数),此时**不会响应新的软中断**,直到当前软中断处理完成。也就是说,在同一个CPU上,软中断执行时不会嵌套执行另一个软中断(即不会被打断)。-但是,硬中断可以打断正在执行的软中断(因为软中断执行时中断是开启的)。-当软中断内核线程ksoftirqd中执行时,由于内核线程运行在进程上下文中,可以被其他中断(包括硬中断和软中断?)打断。但是注意,ksoftirqd线程在处理软中断时,也是调用`do_softirq()`函数,该函数在执行软中断处理程序时会关闭软中断(通过`local_bh_disable`),所以实际上在软中断处理函数执行期间,该CPU不会响应新的软中断(即不会嵌套)。关键点:内核在单个CPU上执行软中断时,会先关闭软中断(即禁止软中断嵌套),以防止软中断的重入。具体来说:-在`do_softirq()`函数中,内核会先关闭当前CPU的软中断(通过`local_bh_disable`),然后处理软中断队列,处理完毕后再开启软中断(`local_bh_enable`)。-因此,在同一个CPU上,一个软中断执行时不会被另一个软中断打断(即不会嵌套)。但是,由于硬中断可以打断软中断,而硬中断处理完成后可能再次触发软中断,这样就会导致软中断的重新调度。结论:-在同一个CPU上,软中断不会打断另一个正在执行的软中断(因为执行软中断时,当前CPU的软中断被禁止)。-但是,不同CPU上的软中断是并行执行的(因为每个CPU有自己的软中断处理队列和ksoftirqd线程),所以不同CPU上的软中断可以同时运行,互不干扰。引用[2]提到,当软中断过多时,内核会唤醒ksoftirqd线程来处理。在ksoftirqd线程中执行软中断时,同样会通过`local_bh_disable`来禁止软中断嵌套,因此也不会被同一个CPU上的其他软中断打断。因此,回答用户的问题:Linux内核中,软中断不会打断另一个正在同一个CPU上执行的软中断。引用文献:[^1]:Linux内核中断分析。[^2]:Linux内核中断/软中断的原理和实现。[^3]:linux中断。[^4]:[Linux内核]软中断与硬中断。[^5]:Linux中断?</think>### Linux内核中软中断的执行机制及打断问题 #### 软中断执行机制 1. **软中断定义** 软中断(softirq)是中断处理的下半部机制,用于延迟处理非紧急任务。它在**开启中断的状态下执行**,因此可被硬中断抢占[^1][^5]。内核定义了软中断向量表(`softirq_vec`),每种软中断有唯一编号和对应的`softirq_action`处理函数[^4]。 2. **触发与执行流程** - 硬中断上半部触发软中断(通过`raise_softirq()`) - 内核在以下时机检查并执行软中断: - 硬中断返回时(`irq_exit()`) - 本地CPU启用软中断时(`local_bh_enable()`) - 内核线程`ksoftirqd`被唤醒时[^2][^5] ```c // 伪代码:软中断处理核心逻辑 void do_softirq() { local_bh_disable(); // 关闭软中断抢占 while (pending_softirqs) { execute_softirq_handlers(); } local_bh_enable(); // 重新启用软中断 } ``` 3. **过载保护机制** 当软中断堆积过多时,内核唤醒`ksoftirqd`线程(优先级最低,nice值19)异步处理,避免用户进程饥饿[^2][^3]。 #### 软中断间的打断问题 **关键结论:软中断不会打断同CPU上正在运行的另一个软中断**,原因如下: 1. **执行时禁止软中断抢占** 在执行软中断前,内核通过`local_bh_disable()`**关闭当前CPU的软中断响应**。这意味着: - 同CPU上:新触发的软中断会挂起,直到当前软中断处理完成[^1][^4] - 不同CPU上:软中断可并行执行(每个CPU有独立软中断状态)[^3] 2. **硬中断优先原则** 软中断执行时**可被硬中断打断**(因中断未关闭),但硬中断结束后: - 若在中断上下文:直接继续执行被中断的软中断 - 若在`ksoftirqd`线程:由线程重新调度执行[^5] 3. **内核线程的异步性** `ksoftirqd`线程处理软中断时: - 仍受`local_bh_disable()`保护 - 可被硬中断或其他高优先级线程抢占,但**不会被其他软中断抢占**[^2] #### 典型场景示例 ```plaintext CPU0 时间线: |-- 硬中断(网卡收包) --| |-- 触发NET_RX软中断 --| |-- 硬中断结束 --| |-- 执行NET_RX软中断(此时禁止软中断抢占) --| |-- 被时钟硬中断打断 --| |-- 时钟中断触发TIMER软中断 --| |-- 时钟中断结束 --| |-- 继续执行NET_RX(未完成的处理) --| |-- 完成NET_RX后启用软中断 --| |-- 执行挂起的TIMER软中断 --| ``` > 此过程中,**NET_RX软中断未被TIMER软中断直接打断**,TIMER仅在NET_RX完成后执行。 ### 总结 - ✅ **不可打断同CPU软中断**:因执行时通过`local_bh_disable()`显式禁止软中断嵌套 - ✅ **可被硬中断打断**:软中断执行时中断保持开启 - ✅ **跨CPU并行**:不同CPU的软异步互不干扰 - ✅ **过载保护**:`ksoftirqd`确保公平性 此设计平衡了实时性和系统稳定性,避免软中断无限递归[^2][^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值