核心調(diào)度器管理活動進程的主要數(shù)據(jù)結(jié)構(gòu)是就緒隊列rq, 每個cpu都有自己的就緒隊列陨溅,而每個活動進程某一時刻只會在一個就緒隊列中庶灿。
對于調(diào)度器而言,由于支持多種調(diào)度算法,所以各種調(diào)度算法的就緒隊列會嵌入到就緒隊列的子隊列中几缭。
就緒隊列具體定義見rq定義
成員名 | 類型 | 說明 | 備注 |
---|
raw_spinlock_t lock;
訪問就緒隊列所使用的鎖 , 可以使用函數(shù)raw_spin_lock_irq()獲取鎖后關(guān)閉中斷,或者使用函數(shù) raw_spin_unlock_irq()釋放鎖并開啟中斷
unsigned int nr_running ;
當前就緒隊列可投入運行的調(diào)度實體個數(shù)沃呢,如進程年栓、線程等調(diào)度實體,但當前正在運行 的調(diào)度實體不計入 nr_running 中,因為它已經(jīng)從就緒隊列中脫離. 函數(shù)nr_running()獲取所有薄霜,同時文件文件 proc/loadavg也可了解相關(guān)信息
#define CPU_LOAD_IDX_MAX 5
unsigned long cpu_load[CPU_LOAD_IDX_MAX];
用于跟蹤 CPU 負載|大小為CPU_LOAD_IDX_MAX某抓,值為5,也可通過文件proc/sched_debug了解負載信息.
unsigned long last_load_update_tick;
更新負載時的時間|在 cpu_load 得到更新時此成員記錄了當前工作時間(jiffies 值)惰瓜。
unsigned long nohz_flags;
用于在動態(tài)時鐘模式開啟時否副,記錄當前時鐘模式|不同模式切換會影響系統(tǒng)進 入不同的系統(tǒng)狀態(tài),通過先前系統(tǒng)狀態(tài)和當前環(huán)境崎坊,系統(tǒng)決定進入不同的系統(tǒng)環(huán)境备禀。
unsigned long last_sched_tick;
配置 CONFIG_NO_HZ_FULL 時,即動態(tài)時鐘啟用時奈揍,記錄上一次調(diào)度 tick|動態(tài)時鐘 管理中曲尸,調(diào)度并不周期性運行,因此需要成員記錄調(diào)度時間男翰。
struct load_weight load;
struct load_weight {
unsigned long weight;
u32 inv_weight;
}
用于跟蹤就緒隊列的負載另患,它是由 Local CPU 上所有可運行的調(diào)度實體共同作用的結(jié)果。成員 weight 用于記錄具體權(quán)重蛾绎,而 inv_weight 則用于優(yōu)先級到權(quán)重的乘數(shù)因子. 一般來說昆箕,在每次 tick 中斷到來時鸦列,系統(tǒng)更新就緒隊列負載
unsigned long nr_load_updates;
當 rq->cpu_load[]成員更新時,該成員記錄更新的次數(shù)鹏倘。在函數(shù) cpu_load_update ()中 更新此值敛熬,此函數(shù)由 cpu_load_update_periodic()調(diào)用,或者在配置 CONFIG_NO_HZ_COMMON 下由函數(shù) cpu_load_update_nohz ()調(diào)用
u64 nr_switches;
用于跟蹤就緒隊列中進程上下文切換的次數(shù)第股。
想了解某個具體進程的切換次數(shù)和調(diào)度信息則可以通過/proc/PID/schedstat 和/proc/PID/sched 兩個文件了解詳細信息|
struct cfs_rq cfs;
struct rt_rq rt;
struct dl_rq dl;
分別對應(yīng):
CFS調(diào)度算法就緒隊列
RT調(diào)度算法就緒隊列
DL調(diào)度算法就緒隊列
struct list_head leaf_cfs_rq_list;
如果需要 CFS 支持組調(diào)度管理应民,那就 得把所有 CFS 加入到一個鏈表當中,leaf_cfs_rq_list 成員就是負責把本 CPU 下的就緒隊列 中各個 CFS 子隊列關(guān)聯(lián)起來夕吻。并且在 cfs_rq 里面有成員 on_list诲锹,其表示當前的 CFS 隊列 leaf_cfs_rq_list 成員是否加入到就緒隊列 rq 的 leaf_cfs_rq_list 管理的鏈表當中。
unsigned long nr_uninterruptible;
用于跟蹤當前系統(tǒng)中隊列里面不可信號中斷的調(diào)度實體個數(shù)
struct task_struct *curr, *idle, *stop
分別用于描述當前正在運行的任務(wù)涉馅,空閑任務(wù)归园,剛剛停止運行的任務(wù);
unsigned long next_balance
用于指示就緒隊列進行下一次負載平衡的時間,該成員在初始化時被設(shè)置為當前系 統(tǒng) jiffies稚矿。
struct mm_struct *prev_mm
就緒隊列中用于保存先前執(zhí)行任務(wù)使用的內(nèi)存描述符 mm_struct 結(jié)構(gòu)庸诱。此成員在發(fā)生調(diào)度時由內(nèi)核函數(shù) context_switch()來更新。
u64 clock;
描述的是隊列的時間晤揣,一般在每個 tick 中 斷到來時更新桥爽,其由上面提到的函數(shù) update_rq_clock()對此成員更新。
u64 clock_task
clock_task 記錄的是 隊列中任務(wù)執(zhí)行的時間昧识,其由函數(shù) update_rq_clock_task()負責更新钠四。
atomic_t nr_iowait
描述當前就緒隊列里面正在進行 IO 等待的進程個數(shù),此成員一般和進程描述符 task_struct 中的 in_iowait 成員配合使用跪楞。
可以通過 proc/stat 下的 procs_blocked 值了解 nr_iowait 的大小
以上是rq基本成員缀去,下面是SMP相關(guān)的成員:
struct llist_head wake_list;
描述了當前隊列中需要喚醒的任務(wù)鏈表.
這個成員在 SMP 下非常重要,其是負載均衡時任務(wù)遷移中間狀態(tài)鏈表.
對于那些需要遷移的任務(wù)來說甸祭,其會由本 CPU 下的就緒隊列脫離出去缕碎,暫時的存 放到目標 CPU 下的就緒隊列的 wake_list 鏈表當中。
struct root_domain *rd;
指示了當前 rq 運行隊列可以工作的 CPU池户,即描述了可以為此就緒隊列服務(wù)的 CPU咏雌。
struct sched_domain *sd
用于描述 rq 就緒隊列所處的調(diào)度域。
unsigned long cpu_capacity
unsigned long cpu_capacity_orig
兩個成員都是用于 rq 就緒隊列的 CPU 能力描述煞檩。在系統(tǒng)初始化時处嫌,兩者都被設(shè)置為 SCHED_CAPACITY_SCALE 值,當前版本中值大小為 1024斟湃。cpu_capacity 是運行過程中使用 的能力熏迹,而 cpu_capacity_orig 則是保存最原始的能力∧可以使用函數(shù) capacity_of()或者 capacity_orig_of()獲取 rq 就緒隊列的 CPU 能力值注暗。用戶可以調(diào)用函數(shù) update_cpu_capacity()更新此能力坛缕。
struct callback_head *balance_callback;
在調(diào)度(_schedule())函數(shù)末尾處的回調(diào)鏈表,每個回調(diào)函數(shù)只會執(zhí)行一次捆昏。
目前僅在RT/DL調(diào)度中使用赚楚。
int active_balance
用于指示是否需要開啟負載均衡操作,在函數(shù) load_balance()對其設(shè)置骗卜。在負載均衡操作中宠页,如果此值被設(shè)置,則內(nèi)核把任務(wù)遷移到空閑 CPU 上運行寇仓。
int push_cpu
用于指示可 push 任務(wù)所在的 CPU举户。在負載均衡操作中,對可 push 的 CPU 選取操 作是一個非常繁瑣的計算過程遍烦,一般會選擇空閑的 CPU 處理遷移的任務(wù)俭嘁。
int cpu
多核環(huán)境中用于指示當前 rq 就緒隊列所在的 CPU。
int online
rq 就緒隊列是否處于工作狀態(tài)服猪,函數(shù) set_rq_online()對其設(shè)置為 1供填,即表示為工作狀態(tài), 而函數(shù) set_rq_offline()對其設(shè)置為 0罢猪,表示處于非工作狀態(tài)近她。
struct list_head cfs_tasks
用于從就緒隊列 rq 角度跟蹤 CFS 就緒隊列中的調(diào)度實體
u64 idle_stamp
用于記錄負載平衡耗費的時間,這個時間是可以記錄到空閑時間中去的坡脐。
u64 avg_idle
用于記錄 CPU 空閑時間泄私,此成員會與上面的 idle_stamp 配合使用。
u64 max_idle_balance_cost
此值與上面 avg_idle 作用類似备闲,其用于跟蹤 CPU 空閑的最大時間。