核心內部與作業系統建構

核心先佔

當程式在使用者模式執行時,排程器幾乎可以在任何一刻打斷它,把 CPU 讓給更緊急的任務。但長久以來,在核心內部執行的程式碼是被豁免的:一旦某個執行緒進入核心(比方說,在一個冗長的檔案操作中途),它就一直佔著 CPU 直到自己選擇放手,即使有遠遠更緊急的東西被喚醒也一樣。核心先佔(kernel preemption)取消了這項豁免——它讓核心能打斷一個正在執行核心程式碼的任務,使更高優先權的任務不必等那個慢吞吞的在核心裡跑完。想像一個收銀檯:在過去,收銀員一旦開始替一大車商品結帳,就沒人能插隊;有了先佔,一位被標記為緊急的顧客可以在任兩件商品之間獲得服務。

具體來說,一個可先佔的核心允許在核心程式碼執行期間於安全點進行重新排程,而不只是在控制權返回使用者空間時。當一個更高優先權的任務變得可執行時,核心可以保存當前任務的核心模式狀態,並立即切換到那個緊急的任務。但在精細的區域裡必須抑制先佔:當持有自旋鎖或正在操作每 CPU 資料時,先佔會被暫時停用,以免任務在臨界區間中途被換出(那可能導致死結或破壞資料)。核心為每個任務維護一個先佔計數器;當它為零且有待處理的重新排程時,才允許先佔。

它對反應速度與即時行為最為重要:沒有核心先佔,一個高優先權的任務可能僅僅因為某個毫不相干的任務正深陷在一次核心呼叫裡,就承受漫長且不可預測的延遲。這正是為什麼會有可先佔以及完全可先佔(PREEMPT_RT)的設定,供低延遲與即時工作使用。誠實的取捨是:先佔增加了開銷與複雜度——能發生切換的地方越多,就越需要小心地鎖定——因此一台純為產出率調校的伺服器可能偏好較少的先佔,而音訊或機器人系統則需要更多。

任務 A 正深陷在一次核心檔案系統操作裡,此時高優先權的任務 B(一個必須交出下一段聲音緩衝的音訊執行緒)被喚醒。在不可先佔的核心上,B 要等到 A 離開核心——可能久到造成可聽見的破音。在可先佔的核心上,核心會在 A 的核心程式碼內下一個安全點切換到 B,音訊便能順暢播放。

核心先佔讓緊急任務得以插進一個仍在核心中執行的任務。

先佔與中斷不同:中斷一定會執行它的處理常式,但它本身並不切換任務;先佔則是排程器決定切換正在執行的任務。關鍵在於,持有自旋鎖時核心會停用先佔——因此在持有自旋鎖時睡眠或阻塞是被禁止的,也是當機的常見原因。

又称
preemptible kernel可搶佔核心