本次分析的kernel**為2.6.32-220。並且我們先不考慮smp。當前linux的排程程式由兩個排程器組成:主排程器,週期性排程器(兩者又統稱為核心排程器);並且每個排程器包括兩個內容:排程框架(其實質就是兩個函式框架)及排程器類。排程器類是實現了不同排程策略的例項,如 cfs、rt class。它們的關係如下圖:
圖 排程器的組成
當前的核心支援兩種排程器類(sched_setscheduler系統呼叫可修改程序的策略):cfs(公平)、rt(實時);5種排程策略:sched_noraml(最常見的策略)、sched_batch(除了不能搶占外與常規任務一樣,允許任務執行更長時間,更好地使用快取記憶體,適合於成批處理的工作)、sched_idle(它甚至比nice 19還有弱,為了避免優先順序反轉使用)和sched_rr(迴圈排程,擁有時間片,結束後放在佇列末)、sched_fifo(沒有時間片,可以執行任意長的時間);其中前面三種策略使用的是cfs排程器類,後面兩種使用rt排程器類。
另外,對於排程框架及排程器類,它們都有自己管理的執行佇列,排程框架只識別rq(其實它也不能算是執行佇列),而對於cfs排程器類它的執行佇列則是cfs_rq(內部使用紅黑樹組織排程實體),實時rt的執行佇列則為rt_rq(內部使用優先順序bitmap+雙向鍊錶組織排程實體)。下圖排程器相關的幾個資料結構的關係:
圖 排程器結構關係圖
rq表示排程框架上的執行佇列(它本身並沒有真正組織排程實體,而是它下面的cfs及rq兩個成員負責組織真正的排程實體),在多核處理器上每個cpu有乙個rq結構.
rq#cpu執行佇列,每個cpu乙個
nr_running:表示總共就緒的程序數(包括cfs,rq及正在執行的)
cpu_load:表示該rq所在cpu的歷史load,一般有5個
load:表示當前cpu的load,這個load是它所有就緒程序的load之和(同樣包括cfs,rq及正在執行的)
nr_swithces:進行上下文切換的次數
cfs:該rq所包括的cfs_rq執行佇列,這個是所有cfs_rq的root
rt:與上面的cfs類似
curr:當前正在執行的程序(這裡不是se,注意跟cfs_rq的curr區分開來)
clock:執行佇列的時鐘,這個時鐘是後面cfs,rq所使用的時鐘,也是大多數proc顯然的時間相關的時鐘
cpu:該rq所屬的cpu
leaf_cfs_rq_list:如果使用的cgroup來建立巢狀的group,那麼這個group的cfs_rq通過該變數組織,注:每個cgroup都有乙個cfs_rq
cfs_rq#cfs排程器類的執行佇列
load:該cfs_rq的load,它只計算它本層下面的se的weight之和,並不是這個se的load,也不是遞迴到葉子節點上的所有se weight之和(理解這點非常重要),這裡有兩個概念要區分清楚:se的load與se的weight,之所以會有這兩個區別是因為組排程的存在,對於乙個組它本身也是乙個se,它也有乙個cfs_rq,所以對於組它的se->weight其實就是我們設定cgroup的cpu.shares的乙個均值(cpu.shares是儲存在tg->shares,而se->weight是通過update_cfs_shares計算出來的,如果它下面的se在乙個cpu裡,那麼它們就相等,否則…還不清楚到底為什麼那樣算的?),而它的cfs_rq的load,則是它下面所有se的weight之和;對於普通的程序,則它本身沒有cfs_rq(它有所屬的cfs_rq),所以它沒有cfs_rq load,只有weight
nr_running:就緒的程序數,只包括本層的(包括正在執行的)
h_nr_running:只對於組才有效,包括底層所有cfs_rq的nr_running之和
exec_lock:該cfs_rq總共占用的cpu時間(物理),只累計本層
min_vruntime:用於調整se的vruntime,它是遞增的,但不一定是該cfs_rq裡所有se最小
tasks_timeline:該cfs_rq的紅黑樹root
rb_leftmost:紅黑樹的最左邊節點
curr:當前執行的se(對於組雖然它不會在cpu上執行,但是當它的下層有乙個task在cpu上執行,那麼它所在的cfs_rq就把它當做是該cfs_rq上當前正在執行的se)
rq:該cfs_rq當前所attach的cpu rq
tg:該cfs_rq所屬的task group,即所屬的組,通過該成員可以找到該cfs_rq對應的組在該cpu上所屬的se,即該cfs_rq自身的se
sched_entity#排程實體
load:排程實體自身的load,對於普通程序這個load跟優先順序成正比,優先順序高的,load大,通過prio_to_weight表可以查詢到它們的對應關係(注意與cfs_rq的load區分開)
run_node:紅黑樹節點
on_rq:表示是否在執行佇列或正在執行(當前執行的程序是不儲存在紅黑樹裡,但它的on_rq還是標誌著的,記住這個也很關鍵)
exec_start:這個並不是表示程序開始執行的時候,而是每次update_curr都會更新該時鐘為當前rq的clock,它主要用於計算上次執行update_curr到這次再執行,總共發的cpu clock,然後再把這個差值加到sum_exec_runtime
sum_exec_runtime:程序總共執行的cpu clock(占用cpu的物理時間)
prev_sum_exec_runtime:上次該程序被排程時已經占用的cpu時間(每次在排程乙個新的程序時都會把它的se->prev_sum_exec_runtime = se->sum_exec_runtime),所以sum_exec_runtime- prev_sum_exec_runtime就是這次排程占用cpu的clock
vruntime:虛擬時間(實現cfs最關鍵的東西),簡單的理解它是執行的cpu clock的乙個虛擬值,這個變換與程序的權重成反比
parent:該se的上級se(只對組排程有用)
cfs_rq:該se就緒時所屬的cfs_rq,在不同cpu上該值是不一樣的(即cfs_rq_of(se)找到的是se所在的父se的my_q)
my_q:該se下面的管理的se組成的cfs_rq(只對組排程有用),這個與cfs_rq的區別很重要,它是該se本身所管理的所有下級se所組成的執行佇列,而cfs_rq則是該se所屬的父級執行佇列
task_group#組結構體,每個group都有乙個task_group結構
se:該tg在每個cpu上的se
cfs_rq:該tg在每個cpu上的cfs_rq
shares:我們用cgroup設定cpu.shares的值
對於實時排程類也是一樣的,它也是支援組排程的,它的執行佇列是使用rt_prio_array active組織的,即bitmap+lists,我們在介紹rt類的時候再詳細介紹。這些欄位的含義也是proc欄位的意思,所以理解這些對於理解proc資訊很有幫助。
儲存器(一) 概述
一 儲存器的分類 儲存器分類的標準很多 我們主要看看按儲存介質 儲存方式和在計算機中的作用分類。1 按儲存介質 1 半導體儲存器 ttl transistor transistor logic 電晶體 和mos metal oxide semiconductor金屬氧化物半導體 ttl 特點 整合度...
linux 系統呼叫(一)概述
linux系統呼叫這部分經常出現兩個詞 libc庫和封裝函式。1.libc概念 libc是stantard c library的簡稱,它是符合ansi c標準的乙個標準函式庫。libc庫提供c語言中所使用的巨集,型別的定義,字串操作符,數學計算函式以及輸入輸出函式等。正如ansi c是c語言的標準一...
型別庫(一) 概述
乙個使用者指南是一本書,一些書的集合就叫做庫了.在ole中,許多元素 物件,介面等等 型別資訊的集合就叫做型別庫 ole的型別資訊服務真正的是乙個建立和操作它包含的型別庫資訊的服務 庫本身只有少量自己的資訊,它主要關心儲存和取出在它內部的元素的型別資訊 所以,在極大程度上,型別庫充當圖書管理員的角色...