1. 程式人生 > >Linux核心搶佔的理解

Linux核心搶佔的理解

可搶佔性,對一個系統的排程延時具有重要意義。2.6 之前,一個程序進入核心態後,別的程序無法搶佔,只能等其完成或退出核心態時才能搶佔, 這帶來嚴重的延時問題,2.6 開始支援核心態搶佔。

禁止核心搶佔的情況列出如下:

(1)核心執行中斷處理例程時不允許核心搶佔,中斷返回時再執行核心搶佔。
(2)當核心執行軟中斷或tasklet時,禁止核心搶佔,軟中斷返回時再執行核心搶佔。 
(3)在臨界區禁止核心搶佔,臨界區保護函式通過搶佔計數巨集控制搶佔,計數大於0,表示禁止核心搶佔。

為保證Linux核心在以上情況下不會被搶佔,搶佔式核心使用了一個變數preempt_ count,稱為核心搶佔鎖。這一變數被設定在程序的PCB結構task_struct中。每當核心要進入以上幾種狀態時,變數preempt_ count就加1,指示核心不允許搶佔。每當核心從以上幾種狀態退出時,變數preempt_ count就減1,同時進行可搶佔的判斷與排程。搶佔式Linux核心的修改主要有兩點:

一是對中斷的入口程式碼和返回程式碼進行修改。在中斷的入口核心搶佔鎖preempt_count加1,以禁止核心搶佔;在中斷的返回處,核心搶佔鎖preempt_count減1,使核心有可能被搶佔。另一基本修改是重新定義了自旋鎖、讀、寫鎖,在鎖操作時增加了對preempt count變數的操作。在對這些鎖進行加鎖操作時preemptcount變數加1,以禁止核心搶佔;在釋放鎖時preemptcount變數減1,並在核心的搶佔條件滿足且需要重新排程時進行搶佔排程。

排程的時機

1) 中斷返回核心空間:檢查preempt_count是否為0和TIF_NEED_RESCHED是否為1 
2) 中斷或異常返回到user space:檢查TIF_NEED_RESCHED是否為1
3)  顯式或者隱式調preemp_enable()函式:檢查preempt_count是否為0和TIF_NEED_RESCHED是否為1
4)使能軟中斷:檢查preempt_count是否為0和TIF_NEED_RESCHED是否為1
5)自己主動schedule()

spinlock不允許睡眠,原因就是他設計初衷就是如此,因此在獲取spinlock時就呼叫禁止搶佔的函式,所以正常情況下獲取鎖的CPU是不會被搶佔的,但如果工程師程式碼中進行了睡眠,那麼睡眠會導致讓出CPU,想象一下,一個低優先順序的執行緒先獲取了spinlock,如果來一個高優先順序的執行緒去獲取spinlock,就會一直獲取不到導致死鎖。