一篇博文,未細考證,貼來學習。也可以參考LKD 4.6節
早期的Linux核心是不可搶佔的。它的調度方法是:一個進程可以通過schedule()函數自願地啟動一次調度。非自願的強制性調度只能發生在每次從系統調用返回的前夕以及每次從中斷或異常處理返回到使用者空間的前夕(這種強制性調度又叫使用者搶佔)。但是,如果在系統空間發生中斷或異常是不會引起調度的。這種方式使核心實現得以簡化。但常存在下面兩個問題:
- 如果這樣的中斷髮生在核心中,本次中斷返回是不會引起調度的,而要到最初使CPU從使用者空間進入核心空間的那次系統調用或中斷(異常)返回時才會發生調度。
- 另外一個問題是優先順序反轉。在Linux中,在核心態啟動並執行任何操作都要優先於使用者態進程,這就有可能導致優先順序反轉問題的出現。例如,一個低優先順序的使用者進程由於執行軟/硬中斷等原因而導致一個高優先順序的任務得不到及時響應。
當前的Linux核心加入了核心搶佔(preempt)機制。核心搶佔指使用者程式在執行系統調用期間可以被搶佔,該進程暫時掛起,使新喚醒的高優先順序進程能夠運行。這種搶佔並非可以在核心中任意位置都能安全進行,比如在臨界區中的代碼就不能發生搶佔。臨界區是指同一時間內不可以有超過一個進程在其中執行的指令序列。在Linux核心中這些部分需要用自旋鎖保護。
核心搶佔要求核心中所有可能為一個以上進程共用的變數和資料結構就都要通過互斥機制加以保護,或者說都要放在臨界區中。在搶佔式核心中,認為如果核心不是在一個中斷處理常式中,並且不在被 spinlock等互斥機制保護的臨界代碼中,就認為可以"安全"地進行進程切換。
Linux核心將臨界代碼都加了互斥機制進行保護,同時,還在已耗用時間過長的代碼路徑上插入調度檢查點,打斷過長的執行路徑,這樣,任務可快速切換進程狀態,也為核心搶佔做好了準備。
Linux核心搶佔只有在核心正在執行例外處理常式(通常指系統調用)並且允許核心搶佔時,才能進行搶佔核心。禁止核心搶佔的情況列出如下:
(1)核心執行中斷處理常式時不允許核心搶佔,中斷返回時再執行核心搶佔。
(2)當核心執行非強制中斷或tasklet時,禁止核心搶佔,非強制中斷返回時再執行核心搶佔。
(3)在臨界區禁止核心搶佔,臨界區保護函數通過搶佔計數宏控制搶佔,計數大於0,表示禁止核心搶佔。
搶佔式核心實現的原理是在釋放自旋鎖時或從中斷返回時,如果當前執行進程的 need_resched被標記,則進行搶佔式調度
詳細背景和實現:http://blog.csdn.net/sailor_8318/article/details/2870184