爲什麼在中斷上下文中不能休眠?

這個問題有很多人問過,我看了下linux得內核代碼,原因如下(當然我不能保證一定對,如果有牛人理解得更好,歡迎指正)
1. 中斷處理的時候,不應該發生進程切換,因爲在中斷context中,唯一能打斷當前中斷handler的只有更高優先級的中斷,它不會被進程打斷(這點對 於softirq,tasklet也一樣,因此這些bottom half也不能休眠),如果在中斷context中休眠,則沒有辦法喚醒它,因爲所有的 wake_up_xxx都是針對某個進程而言的,而在中斷context中,沒有進程的概念,沒有一個task_struct(這點對於softirq和 tasklet一樣),因此真的休眠了,比如調用了會導致block的例程,內核幾乎肯定會死.
2.schedule()在切換進程時,保存當前的進程上下文(CPU寄存器的值、進程的狀態以及堆棧中的內容),以便以後恢復此進程運行。中斷髮生後,內核會先保存當前被中斷的進程上下文(在調用中斷處理程序後恢復);
但在中斷處理程序裏,CPU寄存器的值肯定已經變化了吧(最重要的程序計數器PC、堆棧SP等),如果此時因爲睡眠或阻塞操作調用了schedule(),則保存的進程上下文就不是當前的進程context了.所以不可以在中斷處理程序中調用schedule()。
3.2.4內核中schedule()函數本身在進來的時候判斷是否處於中斷上下文:
if(unlikely(in_interrupt()))
BUG();
因此,強行調用schedule()的結果就是內核BUG,但我看2.6.18的內核schedule()的實現卻沒有這句,改掉了.
4.中斷handler會使用被中斷的進程內核堆棧,但不會對它有任何影響,因爲handler使用完後會完全清除它使用的那部分堆棧,恢復被中斷前的原貌.
5.處於中斷context時候,內核是不可搶佔的,因此,如果休眠,則內核一定掛起.

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

先把中斷處理流程給出來

  1. 1.進入中斷處理程序--->2.保存關鍵上下文---->3.開中斷(sti指令)--->4.進入中斷處理程序的 handler--->5.關中斷(cli指令)---->6.寫EOI寄存器(表示中斷處理完成)---->7.開中斷。
複製代碼


硬中斷:
對應於上圖的1、2、3步驟,在這幾個步驟中,所有中斷是被屏蔽的,如果在這個時候睡眠了,操作系統不會收到任何中斷(包括時鐘中斷),系統就基本處於癱瘓狀態(例如調度器依賴的時鐘節拍沒有等等……)

軟中斷:
對應上圖的4(當然,準確的說應該是4步驟的後面一點,先把話說保險點,免得思一克又開始較真 )。這個時候不能睡眠的關鍵是因爲上下文。
大家知道操作系統以進程調度爲單位,進程的運行在進程的上下文中,以進程描述符作爲管理的數據結構。進程可以睡眠的原因是操作系統可以切換不同進程的上下文,進行調度操作,這些操作都以進程描述符爲支持。
中斷運行在中斷上下文,沒有一個所謂的中斷描述符來描述它,它不是操作系統調度的單位。一旦在中斷上下文中睡眠,首先無法切換上下文(因爲沒有中斷描述符,當前上下文的狀態得不到保存),其次,沒有人來喚醒它,因爲它不是操作系統的調度單位。
此外,中斷的發生是非常非常頻繁的,在一箇中斷睡眠期間,其它中斷髮生並睡眠了,那很容易就造成中斷棧溢出導致系統崩潰。

如 果上述條件滿足了(也就是有中斷描述符,併成爲調度器的調度單位,棧也不溢出了,理論上是可以做到中斷睡眠的),中斷是可以睡眠的,但會引起很多問題.例 如,你在時鐘中斷中睡眠了,那操作系統的時鐘就亂了,調度器也了失去依據;例如,你在一個IPI(處理器間中斷)中,其它CPU都在死循環等你答覆,你確 睡眠了,那其它處理器也不工作了;例如,你在一個DMA中斷中睡眠了,上面的進程還在同步的等待I/O的完成,性能就大大降低了……還可以舉出很多例子。 所以,中斷是一種緊急事務,需要操作系統立即處理,不是不能做到睡眠,是它沒有理由睡眠。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

中斷產生是隨機的,假設某次中斷一個內核線程,而且按照你說的方案,這個線程的task結構就會被借用,線程就會去睡眠。被打斷線程的優先級如果太低,那 麼它很難有機會再執行,某些情況下可能造成系統hang。如果臨時提高被打斷線程的優先級,那麼又需要設計新的喚醒機制來保證阻塞同一鎖上的高優先級的線 程被先喚醒。同時,要實現臨時提高被打斷線程的優先級,又需要再鎖的獲取流程增加改變優先級的算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章