核心調(diào)度器管理活動(dòng)進(jìn)程的主要數(shù)據(jù)結(jié)構(gòu)是就緒隊(duì)列rq, 每個(gè)cpu都有自己的就緒隊(duì)列,而每個(gè)活動(dòng)進(jìn)程某一時(shí)刻只會(huì)在一個(gè)就緒隊(duì)列中。
對(duì)于調(diào)度器而言,由于支持多種調(diào)度算法,所以各種調(diào)度算法的就緒隊(duì)列會(huì)嵌入到就緒隊(duì)列的子隊(duì)列中。
就緒隊(duì)列具體定義見(jiàn)rq定義
| 成員名 | 類(lèi)型 | 說(shuō)明 | 備注 |
|---|
raw_spinlock_t lock;
訪(fǎng)問(wèn)就緒隊(duì)列所使用的鎖 , 可以使用函數(shù)raw_spin_lock_irq()獲取鎖后關(guān)閉中斷,或者使用函數(shù) raw_spin_unlock_irq()釋放鎖并開(kāi)啟中斷
unsigned int nr_running ;
當(dāng)前就緒隊(duì)列可投入運(yùn)行的調(diào)度實(shí)體個(gè)數(shù),如進(jìn)程、線(xiàn)程等調(diào)度實(shí)體,但當(dāng)前正在運(yùn)行 的調(diào)度實(shí)體不計(jì)入 nr_running 中,因?yàn)樗呀?jīng)從就緒隊(duì)列中脫離. 函數(shù)nr_running()獲取所有,同時(shí)文件文件 proc/loadavg也可了解相關(guān)信息
#define CPU_LOAD_IDX_MAX 5
unsigned long cpu_load[CPU_LOAD_IDX_MAX];
用于跟蹤 CPU 負(fù)載|大小為CPU_LOAD_IDX_MAX,值為5,也可通過(guò)文件proc/sched_debug了解負(fù)載信息.
unsigned long last_load_update_tick;
更新負(fù)載時(shí)的時(shí)間|在 cpu_load 得到更新時(shí)此成員記錄了當(dāng)前工作時(shí)間(jiffies 值)。
unsigned long nohz_flags;
用于在動(dòng)態(tài)時(shí)鐘模式開(kāi)啟時(shí),記錄當(dāng)前時(shí)鐘模式|不同模式切換會(huì)影響系統(tǒng)進(jìn) 入不同的系統(tǒng)狀態(tài),通過(guò)先前系統(tǒng)狀態(tài)和當(dāng)前環(huán)境,系統(tǒng)決定進(jìn)入不同的系統(tǒng)環(huán)境。
unsigned long last_sched_tick;
配置 CONFIG_NO_HZ_FULL 時(shí),即動(dòng)態(tài)時(shí)鐘啟用時(shí),記錄上一次調(diào)度 tick|動(dòng)態(tài)時(shí)鐘 管理中,調(diào)度并不周期性運(yùn)行,因此需要成員記錄調(diào)度時(shí)間。
struct load_weight load;
struct load_weight {
unsigned long weight;
u32 inv_weight;
}
用于跟蹤就緒隊(duì)列的負(fù)載,它是由 Local CPU 上所有可運(yùn)行的調(diào)度實(shí)體共同作用的結(jié)果。成員 weight 用于記錄具體權(quán)重,而 inv_weight 則用于優(yōu)先級(jí)到權(quán)重的乘數(shù)因子. 一般來(lái)說(shuō),在每次 tick 中斷到來(lái)時(shí),系統(tǒng)更新就緒隊(duì)列負(fù)載
unsigned long nr_load_updates;
當(dāng) rq->cpu_load[]成員更新時(shí),該成員記錄更新的次數(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;
用于跟蹤就緒隊(duì)列中進(jìn)程上下文切換的次數(shù)。
想了解某個(gè)具體進(jìn)程的切換次數(shù)和調(diào)度信息則可以通過(guò)/proc/PID/schedstat 和/proc/PID/sched 兩個(gè)文件了解詳細(xì)信息|
struct cfs_rq cfs;
struct rt_rq rt;
struct dl_rq dl;
分別對(duì)應(yīng):
CFS調(diào)度算法就緒隊(duì)列
RT調(diào)度算法就緒隊(duì)列
DL調(diào)度算法就緒隊(duì)列
struct list_head leaf_cfs_rq_list;
如果需要 CFS 支持組調(diào)度管理,那就 得把所有 CFS 加入到一個(gè)鏈表當(dāng)中,leaf_cfs_rq_list 成員就是負(fù)責(zé)把本 CPU 下的就緒隊(duì)列 中各個(gè) CFS 子隊(duì)列關(guān)聯(lián)起來(lái)。并且在 cfs_rq 里面有成員 on_list,其表示當(dāng)前的 CFS 隊(duì)列 leaf_cfs_rq_list 成員是否加入到就緒隊(duì)列 rq 的 leaf_cfs_rq_list 管理的鏈表當(dāng)中。
unsigned long nr_uninterruptible;
用于跟蹤當(dāng)前系統(tǒng)中隊(duì)列里面不可信號(hào)中斷的調(diào)度實(shí)體個(gè)數(shù)
struct task_struct *curr, *idle, *stop
分別用于描述當(dāng)前正在運(yùn)行的任務(wù),空閑任務(wù),剛剛停止運(yùn)行的任務(wù);
unsigned long next_balance
用于指示就緒隊(duì)列進(jìn)行下一次負(fù)載平衡的時(shí)間,該成員在初始化時(shí)被設(shè)置為當(dāng)前系 統(tǒng) jiffies。
struct mm_struct *prev_mm
就緒隊(duì)列中用于保存先前執(zhí)行任務(wù)使用的內(nèi)存描述符 mm_struct 結(jié)構(gòu)。此成員在發(fā)生調(diào)度時(shí)由內(nèi)核函數(shù) context_switch()來(lái)更新。
u64 clock;
描述的是隊(duì)列的時(shí)間,一般在每個(gè) tick 中 斷到來(lái)時(shí)更新,其由上面提到的函數(shù) update_rq_clock()對(duì)此成員更新。
u64 clock_task
clock_task 記錄的是 隊(duì)列中任務(wù)執(zhí)行的時(shí)間,其由函數(shù) update_rq_clock_task()負(fù)責(zé)更新。
atomic_t nr_iowait
描述當(dāng)前就緒隊(duì)列里面正在進(jìn)行 IO 等待的進(jìn)程個(gè)數(shù),此成員一般和進(jìn)程描述符 task_struct 中的 in_iowait 成員配合使用。
可以通過(guò) proc/stat 下的 procs_blocked 值了解 nr_iowait 的大小
以上是rq基本成員,下面是SMP相關(guān)的成員:
struct llist_head wake_list;
描述了當(dāng)前隊(duì)列中需要喚醒的任務(wù)鏈表.
這個(gè)成員在 SMP 下非常重要,其是負(fù)載均衡時(shí)任務(wù)遷移中間狀態(tài)鏈表.
對(duì)于那些需要遷移的任務(wù)來(lái)說(shuō),其會(huì)由本 CPU 下的就緒隊(duì)列脫離出去,暫時(shí)的存 放到目標(biāo) CPU 下的就緒隊(duì)列的 wake_list 鏈表當(dāng)中。
struct root_domain *rd;
指示了當(dāng)前 rq 運(yùn)行隊(duì)列可以工作的 CPU,即描述了可以為此就緒隊(duì)列服務(wù)的 CPU。
struct sched_domain *sd
用于描述 rq 就緒隊(duì)列所處的調(diào)度域。
unsigned long cpu_capacity
unsigned long cpu_capacity_orig
兩個(gè)成員都是用于 rq 就緒隊(duì)列的 CPU 能力描述。在系統(tǒng)初始化時(shí),兩者都被設(shè)置為 SCHED_CAPACITY_SCALE 值,當(dāng)前版本中值大小為 1024。cpu_capacity 是運(yùn)行過(guò)程中使用 的能力,而 cpu_capacity_orig 則是保存最原始的能力??梢允褂煤瘮?shù) capacity_of()或者 capacity_orig_of()獲取 rq 就緒隊(duì)列的 CPU 能力值。用戶(hù)可以調(diào)用函數(shù) update_cpu_capacity()更新此能力。
struct callback_head *balance_callback;
在調(diào)度(_schedule())函數(shù)末尾處的回調(diào)鏈表,每個(gè)回調(diào)函數(shù)只會(huì)執(zhí)行一次。
目前僅在RT/DL調(diào)度中使用。
int active_balance
用于指示是否需要開(kāi)啟負(fù)載均衡操作,在函數(shù) load_balance()對(duì)其設(shè)置。在負(fù)載均衡操作中,如果此值被設(shè)置,則內(nèi)核把任務(wù)遷移到空閑 CPU 上運(yùn)行。
int push_cpu
用于指示可 push 任務(wù)所在的 CPU。在負(fù)載均衡操作中,對(duì)可 push 的 CPU 選取操 作是一個(gè)非常繁瑣的計(jì)算過(guò)程,一般會(huì)選擇空閑的 CPU 處理遷移的任務(wù)。
int cpu
多核環(huán)境中用于指示當(dāng)前 rq 就緒隊(duì)列所在的 CPU。
int online
rq 就緒隊(duì)列是否處于工作狀態(tài),函數(shù) set_rq_online()對(duì)其設(shè)置為 1,即表示為工作狀態(tài), 而函數(shù) set_rq_offline()對(duì)其設(shè)置為 0,表示處于非工作狀態(tài)。
struct list_head cfs_tasks
用于從就緒隊(duì)列 rq 角度跟蹤 CFS 就緒隊(duì)列中的調(diào)度實(shí)體
u64 idle_stamp
用于記錄負(fù)載平衡耗費(fèi)的時(shí)間,這個(gè)時(shí)間是可以記錄到空閑時(shí)間中去的。
u64 avg_idle
用于記錄 CPU 空閑時(shí)間,此成員會(huì)與上面的 idle_stamp 配合使用。
u64 max_idle_balance_cost
此值與上面 avg_idle 作用類(lèi)似,其用于跟蹤 CPU 空閑的最大時(shí)間。