現代os都會把時間用「當量quanta」來表示。這樣的單位有助於對不同任務的管理和排程。
os version
tick-freqency
linux2.4
100hz
linux2.6(above)
100,250,300 or1000hz
更高的os具有可選的tick頻率,這種配置一般在開始階段配置。一單系統起來了就不能再改了,但在linux2.6.21之後,引入了dynamic tics可以在系統idle時候忽略tick-timer中斷的發生。
dynamic tic的新增、測試
在menuconfig中新增config_no_hz,在tickless system中。
檢視本地的kernel是否支援dynamic tic,可以如下:
#dmesg | grep -i nohz有如上字樣或者檢視睡眠時的timer次數是否是無規律了:switched to nohz mode on cpu #0
# cat /proc/interrupts | grep -i timeprocess affinity# sleep 10
# cat /proc/interrupts | grep -i time
每個process都有乙個mask標誌哪個cpu可以用它。
重新再cpu間排程並不影響affinity。
2.1時間單位
cfs排程更需要精確的timer機制,需要ns解析度的timer。
2.1cfs情景
當乙個process用完其時間片,將其從active鍊錶移動到expire鍊錶。當active鍊錶元素用光了後,通過指標操作將active和expire鍊錶交換一下。
某個process的時間片長度依賴於其靜態優先順序和在queue中的index。
o(1) scheduler指無論有多少個processes,每次任務切換的時間都是一樣常量。涉及方案:
item
policy
idle
(sched idle)
real-time
(sched fifo sched rr)
fair
(sched normal sched batch)
cfs的policy
item
cfs-policy
sched_normal
應用在normal process中
sched_batch
不允許程序搶占normal的process
2.2 cfs和o(1)的區別對比
優先順序
一般的schedule對process的優先順序的動態考量會依賴:每個task用cpu的時間和每個task等待cpu的時間。
cfs,不會依賴這些資料,而是僅僅看其靜態優先順序
鍊錶
一般的schedule:
用2個鍊錶,乙個active,乙個passive。process全為passive中時,需要swap這兩個表。
cfs:
用乙個紅黑樹來表徵。
時間片
o(1)採用當process用完其timeslice,從active到expire鍊錶時,會重新計算其timeslice。
cfs採用動態時間量子,一單process被選中,立即會計算其timeslice。
virtual time
上邊說了cfs是以乙個紅黑樹來獲得即將執行的process,該紅黑樹主要是以vruntime為鍵值的。把最小的vruntime放到
cfs的排程流程
當用cfs時,其排程有排程開始時、剛排程、排程後持續監聽
排程開始時:當然,在某次timer interrupt中,發現滿足下面的幾個條件,即立即進入cfs排程:會選擇「擁有最小vruntime」或者「最新生成的process」符合這兩個條件的程序來經cfs排程執行。
剛排程
該任務就占有cpu。
排程後持續監聽
每一次的timer interrupt中,核心都會
1、更新virtual runtime,而vruntime是在process一啟動就會開始記錄的。
2、以」current_vruntime - min_vruntime」作為key值存於cfs的排程紅黑樹中。將最小的vruntime放到紅黑樹的最左端。
1、該process用盡其時間片
2、存在比當前process還小的最小的vruntime的process
3、有新建的乙個process
4、某個process剛從sleep中醒來。
cfs提供給user一系列的控制介面可以調整其引數,通過proc檔案系統反映給user。
對其引數的讀寫可以有兩種方式:1、檔案讀寫;2、sysctl系統呼叫
# cat /proc/sys/kernel/sched_latency_ns
# sysctl sched_latency_ns
還可以# echo value > /proc/sys/kernel/sched_latency_ns
# sysctl -w sched_latency_ns=value
2015-9-10 23:51:33
sched_child_runs_first
1,子程序比父程序優先獲得cpu。
0,反之。
sched_compat_yield
0,阻止當前程序交出cpu
sched_wakeup_granularity_ns
值越大,「搶占」成功率越低
sched_migration_cost
當程序從睡眠中喚醒時,該位表示是否「此時」進行一次排程,預設0.5ms。如果當前正在執行的程序的current time和剛剛被喚醒的哪個程序的runtime的均值,小於sched_migration_cost,那麼排程器會選擇該剛剛喚醒的程序。核心配置中一定要開啟wakeup_overlap項。
多核條件下的scheduler
多核涉及乙個負載均衡問題。
sched_migration_cost
把task從乙個cpu0遷移到cpu1,需要看cpu0上的cache是否還有該task的資訊,如果有,那麼就不能把該task遷到cpu1。
該位表示任務在cpu間遷的代價,預設0.5ms。如果該cpu0上的任務的runtime值小於該sched_migration_cost,就表明cache還有東西,不能遷。
sched_nr_migrate
排程器能處理的任務數,預設32.
sched_rt_runtime_us
乙個實時任務的可占用cpu的最大的時間。用完時間後,必須讓出cpu
sched_rt_period_us
cfs排程器需要等待該值的時間才能再次排程runtime任務,這裡只說了runtime任務需要等待的時間。
cfs排程特性
操作/sys/kerenl/debug/sched_features
new_fair_sleepers
cfs中任何乙個被喚醒的task的vruntime都等於紅黑樹中最小的vruntime。
如果該位為yes,則不會是堆笑的vruntime,而是在其本身的值上減去sched_latency_ns,但不會小於其他的等待的task的vruntime
normalized sleeperwakeup_preempt在上面基礎上,該為yes,則sched_latency_ns是個normal值。
被喚醒的task立即搶占cpu。
start_debit
在為乙個新task的vruntime初始化時,如果該為yes,則其vruntime值會遞增乙個量,該量的值等於normalized timeslice。
sync_wakeups
同步喚醒任務。
hrtick
開關高解析度的timer
double tick
yes,中斷來自高解析度的timer**或**系統timer。
no,中斷僅來自高解析度的timer。
asym_gran
影響wake up的粒度值,為yes,sched_wakeup_granularity_ns 是normalized。
更多參考
documentation/scheduler/sched-design-cfs.txt
Linux核心 CFS 完全公平排程演算法
1.cfs的原理 cfs給每乙個程序安排乙個虛擬執行時鐘vruntime,當乙個程序得以執行,隨著時間的推移,vruntime的值不斷的增大。而沒有執行的程序的vruntime的是不會改變的。而排程器總是選擇程序佇列中vrutime最小的程序執行,這就體現了 完全公平性 那如何區分不同程序之間的優先...
完全公平排程
cfs定義了一種新的模型,它給執行佇列中的每個程序都設定了乙個虛擬時鐘,即vruntime。如果乙個程序被排程器投入執行,隨著時間的增長,其vruntime將不斷增大,而沒有得到執行的程序vruntime則不會發生變化。排程器總是選擇vruntime最小的那個程序來執行,這就是所謂的 完全公平 為了...
Linux 完全公平排程器
讀書筆記,linux 系統程式設計 第六章高階程序管理 linux排程器為完全公平排程器,簡稱為cfs。和最近華為鴻蒙提出的確定時延排程相反。完全公平排程器和傳統的unix排程器有很大的區別。在大多數unix系統中,包括引入cfs之前的linux系統,在程序排程中存在兩個基本的基於程序的因素 優先順...