問答
問: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
它的commit log清晰地解釋中斷巢狀可能引入的一些risk,比如stack上限溢位等。也就是說,從這個commit開始,實際Linux已經不再支援中斷的巢狀, 也沒有快慢中斷的概念了,IRQF_DISABLED標記也作廢了。在IRQ HANDLER裡面,無論一個中斷設定還是不設定IRQF_DISABLED, 核心都不會開啟CPU對中斷的響應:
這個作廢的IRQF_DISABLED標記,在核心已經沒有任何的意義了。後來,這個標記本身,在核心裡面也被刪除了,徹底成為過往:
硬體
中斷發生後,一般硬體會自動遮蔽CPU對中斷的響應,而軟體層面上,直到IRQ HANDLER做完,才會重新開啟中斷。比如,對於ARM處理器而言,exception進來的時候,硬體都會自動遮蔽中斷:
也就是說,當ARM處理器收到中斷的時候,它進入中斷樣式,同時ARM處理器的CPSR暫存器的IRQ位會被硬體設定為遮蔽IRQ。
Linux核心會在如下2個時候重新開啟CPSR對IRQ的響應:
1. 從IRQ HANDLER傳回中斷底半部的SOFTIRQ
2. 從IRQ HANDLER傳回一個執行緒背景關係
從1大家可以看出,SOFTIRQ裡面是可以響應中斷的。
(完)