上面顯示的這個文件的內容就是系統中用來控制kernel/sched/features.h這個文件所列內容的開關文件,其中WAKEUP_PREEMPTION表示:目前的系統狀態是打開sleep喚醒進程的搶占屬性的??梢允褂萌缦旅铌P閉這個屬性:
其他相關參數的調整也是類似這樣的方式。其他我沒講到的屬性的含義,大家可以看kernel/sched/features.h文件中的注釋。
系統中還提供了一個sched_wakeup_granularity_ns配置文件,這個文件的值決定了喚醒進程是否可以搶占的一個時間粒度條件。默認CFS的調度策略是,如果喚醒的進程vruntime小于當前正在執行的進程,那么就會發生喚醒進程搶占的情況。而sched_wakeup_granularity_ns這個參數是說,只有在當前進程的vruntime時間減喚醒進程的vruntime時間所得的差大于sched_wakeup_granularity_ns時,才回發生搶占。就是說sched_wakeup_granularity_ns的值越大,越不容易發生搶占。
CFS和其他調度策略
SCHED_BATCH
在上文中我們說過,CFS調度策略主要是針對chrt命令顯示的SCHED_OTHER范圍的進程,實際上就是一般的非實時進程。我們也已經知道,這樣的一般進程還包括另外兩種:SCHED_BATCH和SCHED_IDLE。在CFS的實現中,集成了對SCHED_BATCH策略的支持,并且其功能和SCHED_OTHER策略幾乎是一致的。唯一的區別在于,如果一個進程被用chrt命令標記成SCHED_OTHER策略的話,CFS將永遠認為這個進程是CPU消耗型的進程,不會對其進行IO消耗進程的時間補償。這樣做的唯一目的是,可以在確認進程是CPU消耗型的進程的前提下,對其盡可能的進行批處理方式調度(batch),以減少進程切換帶來的損耗,提高吞度量。實際上這個策略的作用并不大,內核中真正的處理區別只是在標記為SCHED_BATCH時進程在sched_yield主動讓出cpu的行為發生是不去更新cfs的隊列時間,這樣就讓這些進程在主動讓出CPU的時候(執行sched_yield)不會紀錄其vruntime的更新,從而可以繼續優先被調度到。對于其他行為,并無不同。
SCHED_IDLE
如果一個進程被標記成了SCHED_IDLE策略,調度器將認為這個優先級是很低很低的,比nice值為19的優先級還要低。系統將只在CPU空閑的時候才會對這樣的進程進行調度執行。若果存在多個這樣的進程,它們之間的調度方式跟正常的CFS相同。
SCHED_DEADLINE
最新的Linux內核還實現了一個最新的調度方式叫做SCHED_DEADLINE。跟IO調度類似,這個算法也是要實現一個可以在最終期限到達前讓進程可以調度執行的方法,保證進程不會餓死。目前大多數系統上的chrt還沒給配置接口,暫且不做深入分析。
另外要注意的是,SCHED_BATCH和SCHED_IDLE一樣,只能對靜態優先級(即nice值)為0的進程設置。操作命令如下:
多CPU的CFS調度
在上面的敘述中,我們可以認為系統中只有一個CPU,那么相關的調度隊列只有一個。實際情況是系統是有多核甚至多個CPU的,CFS從一開始就考慮了這種情況,它對每個CPU核心都維護一個調度隊列,這樣每個CPU都對自己的隊列進程調度即可。這也是CFS比O1調度算法更高效的根本原因:每個CPU一個隊列,就可以避免對全局隊列使用大內核鎖,從而提高了并行效率。當然,這樣最直接的影響就是CPU之間的負載可能不均,為了維持CPU之間的負載均衡,CFS要定期對所有CPU進行load balance操作,于是就有可能發生進程在不同CPU的調度隊列上切換的行為。這種操作的過程也需要對相關的CPU隊列進行鎖操作,從而降低了多個運行隊列帶來的并行性。不過總的來說,CFS的并行隊列方式還是要比O1的全局隊列方式要高效。尤其是在CPU核心越來越多的情況下,全局鎖的效率下降顯著增加。
CFS對多個CPU進行負載均衡的行為是idle_balance()函數實現的,這個函數會在CPU空閑的時候由schedule()進行調用,讓空閑的CPU從其他繁忙的CPU隊列中取進程來執行。我們可以通過查看/proc/sched_debug的信息來查看所有CPU的調度隊列狀態信息以及系統中所有進程的調度信息。內容較多,我就不在這里一一列出了,有興趣的同學可以自己根據相關參考資料(最好的資料就是內核源碼)了解其中顯示的相關內容分別是什么意思。
原文轉自:http://www.testwo.com/article/659