核心搶占和低延遲

2021-06-19 03:43:58 字數 2656 閱讀 2806

2.8.3 核心搶占和低延遲相關工作(2)

如果可以搶占,則需要執行下列步驟:

kernel/sched.c   

do  while (unlikely(test_thread_flag(tif_need_resched))); 

在呼叫排程器之前,搶占計數器的值設定為preempt_active。這設定了搶占計數器中的乙個標誌位,使之有乙個很大的值,這樣就不受普通的搶占計數器加1操作的影響了,如圖2-30所示。它向schedule函式表明,排程不是以普通方式引發的,而是由於核心搶占。在核心重排程之後,**流程回到當前程序。此時標誌位已經再次移除,這可能是在一段時間之後,此間的這段時間供搶先的程序執行。

圖2-30 程序的搶占計數器

此前我忽略了該標誌與schedule的關係,因此必須在這裡討論。我們知道,如果程序目前不處於可執行狀態,則排程器會用deactivate_task停止其活動。實際上,如果排程是由搶占機制發起的(檢視搶占計數器中是否設定了preempt_active),則會跳過該操作:

kernel/sched.c   

asmlinkage void __sched schedule(void)  else   

}  ...  

這確保了盡可能快速地選擇下乙個程序,而無需停止當前程序的活動。如果乙個高優先順序程序在等待排程,則排程器類將會選擇該程序,使其執行。

該方法只是觸發核心搶占的一種方法。另一種啟用搶占的可能方法是在處理了乙個硬體中斷請求之後。如果處理器在處理中斷請求後返回核心態(返回使用者狀態則沒有影響),特定於體系結構的彙編例程會檢查搶占計數器值是否為0,即是否允許搶占,以及是否設定了重排程標誌,類似於preempt_schedule的處理。如果兩個條件都滿足,則呼叫排程器,這一次是通過preempt_schedule_ irq,表明搶占請求發自中斷上下文。該函式和preempt_schedule之間的本質區別是,preempt_ schedule_irq呼叫時停用了中斷,防止中斷造成遞迴呼叫。

根據本節講述的方法可知,啟用了搶占特性的核心能夠比普通核心更快速地用緊急程序替代當前程序。

2. 低延遲

當然,即使沒有啟用核心搶占,核心也很關注提供良好的延遲時間。例如,這對於網路伺服器是很重要的。儘管此類環境不需要核心搶占引入的開銷,但核心仍然應該以合理的速度響應重要的事件。例如,如果一網路請求到達,需要守護程序處理,那麼該請求不應該被執行繁重io操作的資料庫過度延遲。我已經討論了核心提供的一些用於緩解該問題的措施:cfs和核心搶占中的排程延遲。第5章中將討論的實時互斥量也有助於解決該問題,但還有乙個與排程有關的操作能夠對此有所幫助。

基本上,核心中耗時長的操作不應該完全佔據整個系統。相反,它們應該不時地檢測是否有另乙個程序變為可執行,並在必要的情況下呼叫排程器選擇相應的程序執行。該機制不依賴於核心搶占,即使核心連編時未指定支援搶占,也能夠降低延遲。

發起有條件重排程的函式是cond_resched。其實現如下:

kernel/sched.c   

int __sched cond_resched(void)   

return 0;  

need_resched檢查是否設定了tif_need_resched標誌,**另外還保證核心當前沒有被搶占 ,因此允許重排程。只要兩個條件滿足,那麼__cond_resched會處理必要的細節並呼叫排程器。

如何使用cond_resched?舉例來說,考慮核心讀取與給定記憶體對映關聯的記憶體頁的情況。這可以通過無限迴圈完成,直至所有需要的資料讀取完畢:

for (;;)  

/* 讀入資料 */  

if (exit_condition)  

continue;  

如果需要大量的讀取操作,可能耗時會很長。由於程序執行在核心空間中,排程器無法象在使用者空間那樣撤銷其cpu,假定也沒有啟用核心搶占。通過在每個迴圈迭代中呼叫cond_resched,即可改進此種情況。

for (;;)  

cond_resched();  

/* 讀入資料 */  

if (exit_condition)  

continue;  

核心**已經仔細核查過,以找出長時間執行的函式,並在適當之處插入對cond_resched的呼叫。即使沒有顯式核心搶占,這也能夠保證較高的響應速度。

遵循長期以來的unix核心傳統,linux的程序狀態也支援可中斷的和不可中斷的睡眠。但在2.6.25的開發周期中,又新增了另乙個狀態:task_killable。 處於此狀態程序正在睡眠,不響應非致命訊號,但可以被致命訊號殺死,這剛好與task_uninterruptible相反。在撰寫本書時,核心中適用於task_killable睡眠之處,都還沒有修改。

在核心2.6.25和2.6.26開發期間,排程器的清理相對而言是比較多的。 在這期間增加的乙個新特性是實時組排程。這意味著,通過本章介紹的組排程框架,現在也可以處理實時程序了。

另外,排程器相關的文件移到了乙個專用目錄documentation/scheduler/下,舊的o(1)排程器的相關文件都已經過時,因而刪除了。有關實時組排程的文件可以參考documentation/scheduler/ sched-rt-group.txt。

核心搶占VS使用者搶占

使用者搶占 核心即將返回使用者空間的時候,如果need resched被設定,會導致schedule 被呼叫,此時就會發生使用者搶占。在核心返回使用者空間的時候,它知道自己是安全的,因為既然它可以繼續去執行當前程序,那麼它當然可以再去選擇乙個新的程序去執行。所以核心無論是從中斷處理程式還是在系統呼叫...

核心搶占和中斷(區別)

三 核心可搶占以及可搶占和可中斷的區別 四 搶占 五 中斷 搶占是核心對程序的管理 當高優先順序的任務因中斷而成為就緒,特定的低優先順序程序將讓出cpu,而那個高優先順序的程序得到cpu。可以這樣 簡單地 說,中斷是因為硬體,而搶占是因為中斷帶來特定事件的發生。一般來說,cpu在任何時刻都處於以下三...

Linux 核心搶占

核心搶占 kernel preemption 是一種有效的降低系統響應延時的方法。在核心裡,有三個相關的配置選項。顧名思義,不開啟核心搶占。這是很多伺服器的預設配置選項。在沒有開啟核心搶占的時候,程序的排程時機僅僅發生在非常有限的幾處 程序自己主動觸發排程,例如 通過sleep schedule y...