linux内核2.6.28调度相关的数据结构分析

 

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

你可能感兴趣的:(数据结构,linux内核,struct,list,class,migration)