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
};