1、struct cfs_rq
在rq中與cfs相關的字段
/* CFS-related fields in a runqueue */
struct cfs_rq {
/*
該cfs_rq的load,它只計算它本層下面的se的weight之和,並不是這個se的load,也不是遞歸到葉子節點上的所有se weight之和(理解這點非常重要)*/
struct load_weight load;/*所有進程的累計負荷值*/
//h_nr_running只對於組纔有效,包括底層所有cfs_rq的nr_running之和
unsigned int nr_running, h_nr_running;nr_running/*當前就緒隊列的進程數*/
u64 exec_clock;//該cfs_rq總共佔用的cpu時間(物理),只累計本層
/*
* 當前CFS隊列上最小運行時間,單調遞增
* 兩種情況下更新該值:
* 1、更新當前運行任務的累計運行時間時
* 2、當任務從隊列刪除去,如任務睡眠或退出,這時候會查看剩下的任務的vruntime是否大於min_vruntime,如果是則更新該值。
*/
//用於調整se的vruntime,它是遞增的,但不一定是該cfs_rq裏所有se最小
u64 min_vruntime; //該cpu運行隊列的vruntime推進值, 一般是紅黑樹中最小的vruntime值
#ifndef CONFIG_64BIT
u64 min_vruntime_copy;
#endif
struct rb_root tasks_timeline;/*紅黑樹的頭結點*/
struct rb_node *rb_leftmost;/*紅黑樹的最左面節點*/
/*
* 'curr' points to currently running entity on this cfs_rq.
* It is set to NULL otherwise (i.e when none are currently running).
*/
// current是正在被調用的實體對象
//當前運行的se(對於組雖然它不會在cpu上運行,但是當它的下層有一個task在cpu上運行,那麼它所在的cfs_rq就把它當做是該cfs_rq上當前正在運行的se)
struct sched_entity *curr, *next, *last, *skip;
/*
* 'curr' points to currently running entity on this cfs_rq.
* It is set to NULL otherwise (i.e when none are currently running).
* curr: 當前正在運行的sched_entity(對於組雖然它不會在cpu上運行,但是當它的下層有一個task在cpu上運行,那麼它所在的cfs_rq就把它當做是該cfs_rq上當前正在運行的sched_entity)
* next: 表示有些進程急需運行,即使不遵從CFS調度也必須運行它,調度時會檢查是否next需要調度,有就調度next
*
* skip: 略過進程(不會選擇skip指定的進程調度)
*/
#ifdef CONFIG_SCHED_DEBUG
unsigned int nr_spread_over;
#endif
#ifdef CONFIG_SMP
/*
* CFS load tracking
*/
struct sched_avg avg;
u64 runnable_load_sum;
unsigned long runnable_load_avg;
#ifdef CONFIG_64BIT_ONLY_CPU
unsigned long runnable_load_avg_32bit;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
unsigned long tg_load_avg_contrib;
unsigned long propagate_avg;
#endif
atomic_long_t removed_load_avg, removed_util_avg;
#ifndef CONFIG_64BIT
u64 load_last_update_time_copy;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
/*
* h_load = weight * f(tg)
*
* Where f(tg) is the recursive weight fraction assigned to
* this group.
*/
unsigned long h_load;
u64 last_h_load_update;
struct sched_entity *h_load_next;
#endif /* CONFIG_FAIR_GROUP_SCHED */
#endif /* CONFIG_SMP */
#ifdef CONFIG_FAIR_GROUP_SCHED
/* 所屬於的CPU rq */
struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */
/*
* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
* a hierarchy). Non-leaf lrqs hold other higher schedulable entities
* (like users, containers etc.)
*
* leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
* list is used during load balance.
*/
int on_list;
struct list_head leaf_cfs_rq_list;
/*屬於這個cfs_rq的進程組*/
struct task_group *tg; /* group that "owns" this runqueue */
#ifdef CONFIG_SCHED_WALT
u64 cumulative_runnable_avg;
#endif
#ifdef CONFIG_CFS_BANDWIDTH
int runtime_enabled;
u64 runtime_expires;
s64 runtime_remaining;
u64 throttled_clock, throttled_clock_task;
u64 throttled_clock_task_time;
int throttled, throttle_count, throttle_uptodate;
struct list_head throttled_list;
#endif /* CONFIG_CFS_BANDWIDTH */
#endif /* CONFIG_FAIR_GROUP_SCHED */
};
2、task_struct
每個task對應一個se,但是反過去不一定成立,因爲有task_group的概念
struct task_struct
{
........
/* 表示是否在運行隊列 */
int on_rq;
/* 進程優先級
* prio: 動態優先級,範圍爲100~139,與靜態優先級和補償(bonus)有關
* static_prio: 靜態優先級,static_prio = 100 + nice + 20 (nice值爲-20~19,所以static_prio值爲100~139)
* normal_prio: 沒有受優先級繼承影響的常規優先級,具體見normal_prio函數,跟屬於什麼類型的進程有關
*/
int prio, static_prio, normal_prio;
/* 實時進程優先級 */
unsigned int rt_priority;
/* 調度類,調度處理函數類 */
const struct sched_class *sched_class;
/* 調度實體(紅黑樹的一個結點) */
struct sched_entity se; //通過這個調度實體可以找到對應的task
/* 調度實體(實時調度使用) */
struct sched_rt_entity rt;
struct sched_dl_entity dl;
#ifdef CONFIG_CGROUP_SCHED
/* 指向其所在進程組 */
struct task_group *sched_task_group;
#endif
........
}