struct task_struct {
//進程的當前運行狀態
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
unsigned int flags; /* per process flags, defined below */
//動態優先順序,靜態優先順序和常規優先順序
int prio, static_prio, normal_prio;
//即時優先順序
unsigned int rt_priority;
const struct sched_class *sched_class;/*調度類指標,一堆指向函數的指標*/
//CFS 調度實體
struct sched_entity se;
//即時調度實體
struct sched_rt_entity rt;
unsigned int policy;/*進程的調度類型*/
struct list_head tasks;/*進程組織鏈表*/
/*環境切換次數*/
unsigned long nvcsw, nivcsw; /* context switch counts */
}
2 sched_class,進程調度類:
包括fair_sched_class,rt_sched_class和idle_sched_class,它們調用的順序是:
(1)rq->nr_running == rq->cfs.nr_running說明沒有即時進程,就去執行fair_sched_class的pick_next_task()
if (likely(rq->nr_running == rq->cfs.nr_running)) {
p = fair_sched_class.pick_next_task(rq);
if (likely(p))
return p;
}
(2)
/*有即時進程,切換到即時調度類*/
class = sched_class_highest;/*這裡就預設即時進程類了*/
for ( ; ; ) {
p = class->pick_next_task(rq);
/*是什麼導致了rq->nr_running != rq->cfs.nr_running,
但是rt_rq->rt_nr_running=0呢*/
if (p)
return p;
/*
* Will never be NULL as the idle class always
* returns a non-NULL p:
*/
/**/
(3)沒有即時進程就切換調度類
class = class->next;/*這是指向了fair_sched_class*/
(4)在即時調度類裡面也沒有進程,即cfs_rq->nr_running = 0;就切換到idle_sched_class,它又調用pick_next_task_idle();選擇idle進程來運行。
}
3 每CPU運行隊列rq
struct rq {
/* runqueue lock: */
spinlock_t lock;
/*
* nr_running and cpu_load should be in the same cacheline because
* remote CPUs use both these fields when doing load calculation.
*/
//rq中進程的數目,是否是即時進程和完全公平進程的總數目,有待驗證????
unsigned long nr_running;
#define CPU_LOAD_IDX_MAX 5
unsigned long cpu_load[CPU_LOAD_IDX_MAX];
unsigned char idle_at_tick;
#ifdef CONFIG_NO_HZ
unsigned long last_tick_seen;
unsigned char in_nohz_recently;
#endif
/* capture load from *all* tasks on this cpu: */
struct load_weight load;
unsigned long nr_load_updates;
//這個運行隊列的切換次數
u64 nr_switches;
//注意這兩個資料結構,他們表明了rq 和cf_rq、rt_rq之間的關係,即實際的調度實體是在cf_rq、rt_rq上
//rq只是記錄了一些全域的資訊
struct cfs_rq cfs;
struct rt_rq rt;
#ifdef CONFIG_FAIR_GROUP_SCHED
/* list of leaf cfs_rq on this cpu: */
struct list_head leaf_cfs_rq_list;
#endif
#ifdef CONFIG_RT_GROUP_SCHED
struct list_head leaf_rt_rq_list;
#endif
/*
* This is part of a global counter where only the total sum
* over(統計) all CPUs matters. A task can increase this counter on
* one CPU and if it got migrated afterwards it may decrease
* it on another CPU. Always updated under the runqueue lock:
*/
unsigned long nr_uninterruptible;
struct task_struct *curr, *idle;
unsigned long next_balance;
struct mm_struct *prev_mm;
u64 clock;
atomic_t nr_iowait;
#ifdef CONFIG_SMP
struct root_domain *rd;
struct sched_domain *sd;
/* For active balancing */
int active_balance;
int push_cpu;
/* cpu of this runqueue: */
int cpu;
int online;
unsigned long avg_load_per_task;
struct task_struct *migration_thread;
struct list_head migration_queue;
#endif
#ifdef CONFIG_SCHED_HRTICK
#ifdef CONFIG_SMP
int hrtick_csd_pending;
struct call_single_data hrtick_csd;
#endif
struct hrtimer hrtick_timer;
#endif
#ifdef CONFIG_SCHEDSTATS
/* latency stats */
struct sched_info rq_sched_info;
/* sys_sched_yield() stats */
unsigned int yld_exp_empty;
unsigned int yld_act_empty;
unsigned int yld_both_empty;
unsigned int yld_count;
/* schedule() stats */
unsigned int sched_switch;
unsigned int sched_count;
unsigned int sched_goidle;
/* try_to_wake_up() stats */
unsigned int ttwu_count;
unsigned int ttwu_local;
/* BKL stats */
unsigned int bkl_count;
#endif
};
4 sched_entity 調度實體,它又分cfs調度實體和即時調度實體
(1)cfs調度實體
struct sched_entity {
//當前調度實體所佔的權重
struct load_weight load; /* for load-balancing *//*nice 對應的load值*/
//調度實體在紅/黑樹狀結構中的記錄資訊
struct rb_node run_node;
//當前調度實體屬於哪一個調度組
struct list_head group_node;
//當前的調度實體是否在運行隊列上
unsigned int on_rq;
u64 exec_start;/*上次開始調度時的已耗用時間*/
u64 sum_exec_runtime;/*總的已耗用時間*/
u64 vruntime;//當前調度實體的虛擬已耗用時間
u64 prev_sum_exec_runtime;
u64 last_wakeup;
u64 avg_overlap;
#ifdef CONFIG_SCHEDSTATS
u64 wait_start;
u64 wait_max;
u64 wait_count;
u64 wait_sum;
u64 sleep_start;
u64 sleep_max;
s64 sum_sleep_runtime;
u64 block_start;
u64 block_max;
u64 exec_max;
u64 slice_max;
u64 nr_migrations;
u64 nr_migrations_cold;
u64 nr_failed_migrations_affine;
u64 nr_failed_migrations_running;
u64 nr_failed_migrations_hot;
u64 nr_forced_migrations;
u64 nr_forced2_migrations;
u64 nr_wakeups;
u64 nr_wakeups_sync;
u64 nr_wakeups_migrate;
u64 nr_wakeups_local;
u64 nr_wakeups_remote;
u64 nr_wakeups_affine;
u64 nr_wakeups_affine_attempts;
u64 nr_wakeups_passive;
u64 nr_wakeups_idle;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
struct sched_entity *parent;
/* rq on which this entity is (to be) queued: */
struct cfs_rq *cfs_rq;
/* rq "owned" by this entity/group: */
struct cfs_rq *my_q;
#endif
};
(2)sched_rt_entity
struct sched_rt_entity {
struct list_head run_list;
//到期時間
unsigned long timeout;
//時間片
unsigned int time_slice;
//cpu的數量
int nr_cpus_allowed;
struct sched_rt_entity *back;
#ifdef CONFIG_RT_GROUP_SCHED
struct sched_rt_entity *parent;
/* rq on which this entity is (to be) queued: */
struct rt_rq *rt_rq;
/* rq "owned" by this entity/group: */
struct rt_rq *my_q;
#endif
};
5 cfs_rq 公平調度隊列
/* CFS-related fields in a runqueue */
struct cfs_rq {
//這個和sched_entity的權重有什麼區別????
struct load_weight load;
//cfs_rq中進程的數目
unsigned long nr_running;
u64 exec_clock;
//最小的虛擬已耗用時間,不一定是最小的調度實體的虛擬已耗用時間,但相差無幾
u64 min_vruntime;
struct rb_root tasks_timeline;
struct rb_node *rb_leftmost;
struct list_head tasks;
struct list_head *balance_iterator;
/*
* 'curr' points to currently running entity on this cfs_rq.
* It is set to NULL otherwise (i.e when none are currently running).
*/
struct sched_entity *curr, *next, *last;
unsigned int nr_spread_over;
#ifdef CONFIG_FAIR_GROUP_SCHED
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.
*/
struct list_head leaf_cfs_rq_list;
struct task_group *tg; /* group that "owns" this runqueue */
#ifdef CONFIG_SMP
/*
* the part of load.weight contributed by tasks
*/
unsigned long task_weight;
/*
* h_load = weight * f(tg)
*
* Where f(tg) is the recursive weight fraction assigned to
* this group.
*/
unsigned long h_load;
/*
* this cpu's part of tg->shares
*/
unsigned long shares;
/*
* load.weight at the time we set shares
*/
unsigned long rq_weight;
#endif
#endif
};
6 即時隊列
struct rt_rq {
struct rt_prio_array active;
unsigned long rt_nr_running;
#if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED
int highest_prio; /* highest queued rt task prio */
#endif
#ifdef CONFIG_SMP
unsigned long rt_nr_migratory;
int overloaded;
#endif
int rt_throttled;
u64 rt_time;
u64 rt_runtime;
/* Nests inside the rq lock: */
spinlock_t rt_runtime_lock;
#ifdef CONFIG_RT_GROUP_SCHED
unsigned long rt_nr_boosted;
struct rq *rq;
struct list_head leaf_rt_rq_list;
struct task_group *tg;
struct sched_rt_entity *rt_se;
#endif
};