在面试官:为什么在中断里不能sleep | Linux 内核一文中,作者逐层深入地讲解了为什么中断中为什么不能sleep
,并给出了ISR
里处理耗时工作的解决办法,建议先行阅读。
文中把问题“中断中为什么不能sleep”逐步精确为“为什么在 Linux 里,ISR 被设计成不能睡眠”,讲得很好。但是,对于接下来讲解为什么不能sleep这一部分,(可能是因为我操作系统基础不好)对我来说讲解逻辑却显得不怎么清晰。下面就记录一下自己的理解。
结合下图讲解一下。假如系统正在执行thread 1
,其中有操作critical section
的代码,这时来了一个硬件中断,在ISR
中,有sleep
的操作。由于sleep
会call scheduler
,在进行调度时,可能会调用thread 2
。如果thread 1
持有一个锁lock1
, 而thread 2
中在等待这个锁lock1
,那么,就会造成死锁。
其实,文中也有一张图,可以解释上面的逻辑:
可以看出,如果在上图中,系统调度时,又调度回了thread 1
,那么,就不会产生死锁。这也就是原文中提到的 “top half 在收到中断后立即运行,仅执行时间紧迫的工作,例如确认收到中断或重置硬件,执行完 top half 后,如果进入 ISR 前是处于 critical section 且内核抢占是被关闭 ( 例如 spinlock ) 的话,就会返回到 critical section 里继续运行,不会产生 race condition 的问题”
最后,由于有bottom half
,像sleep
这样耗时的操作完全可以放在bottom half
里,所以也不会产生死锁了。