调度器 sched_class 结构体
调度器 需要做的动作都抽象出来,放在 接口 sched_class 里面,结构体定义在 linux/kernel/sched/sched.h
里面都是 函数指针, 定义了各种调度操作。
示例:
enqueue_task - 将 task * p 加入到 rq 里面;
需要 根据这儿的函数原型,实现函数,然后将函数指针填入到 sched_class 定义的对象里面。
kernel 中定义了 5 个 sched_class 的对象; stop_sched_class ; dl_sched_class ; rt_sched_class ; fair_sched_class ; idle_sched_class ;
1779struct sched_class {
1785 void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
1786 void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
1787 void (*yield_task) (struct rq *rq);
1788 bool (*yield_to_task)(struct rq *rq, struct task_struct *p);
1789
1790 void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags);
1791
1792 struct task_struct *(*pick_next_task)(struct rq *rq);
1793
1794 void (*put_prev_task)(struct rq *rq, struct task_struct *p);
1795 void (*set_next_task)(struct rq *rq, struct task_struct *p, bool first);
1796
1797#ifdef CONFIG_SMP
1798 int (*balance)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
1799 int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
1800 void (*migrate_task_rq)(struct task_struct *p, int new_cpu);
1801
1802 void (*task_woken)(struct rq *this_rq, struct task_struct *task);
1803
1804 void (*set_cpus_allowed)(struct task_struct *p,
1805 const struct cpumask *newmask);
1806
1807 void (*rq_online)(struct rq *rq);
1808 void (*rq_offline)(struct rq *rq);
1809#endif
1810
1811 void (*task_tick)(struct rq *rq, struct task_struct *p, int queued);
1812 void (*task_fork)(struct task_struct *p);
1813 void (*task_dead)(struct task_struct *p);
1814
1815 /*
1816 * The switched_from() call is allowed to drop rq->lock, therefore we
1817 * cannot assume the switched_from/switched_to pair is serliazed by
1818 * rq->lock. They are however serialized by p->pi_lock.
1819 */
1820 void (*switched_from)(struct rq *this_rq, struct task_struct *task);
1821 void (*switched_to) (struct rq *this_rq, struct task_struct *task);
1822 void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
1823 int oldprio);
1824
1825 unsigned int (*get_rr_interval)(struct rq *rq,
1826 struct task_struct *task);
1827
1828 void (*update_curr)(struct rq *rq);
1829
1830#define TASK_SET_GROUP 0
1831#define TASK_MOVE_GROUP 1
1832
1833#ifdef CONFIG_FAIR_GROUP_SCHED
1834 void (*task_change_group)(struct task_struct *p, int type);
1835#endif
1836} __aligned(STRUCT_ALIGNMENT); /* STRUCT_ALIGN(), vmlinux.lds.h */
1837
stop_sched_class ; dl_sched_class ; rt_sched_class ; fair_sched_class ; idle_sched_class优先级
声明在: linux/kernel/sched/sched.h 中; 1863 ~1867 行
1850/* Defined in include/asm-generic/vmlinux.lds.h */
1851extern struct sched_class __begin_sched_classes[];
1852extern struct sched_class __end_sched_classes[];
1853
1854#define sched_class_highest (__end_sched_classes - 1)
1855#define sched_class_lowest (__begin_sched_classes - 1)
1856
1857#define for_class_range(class, _from, _to) \
1858 for (class = (_from); class != (_to); class--)
1859
1860#define for_each_class(class) \
1861 for_class_range(class, sched_class_highest, sched_class_lowest)
1862
1863extern const struct sched_class stop_sched_class;
1864extern const struct sched_class dl_sched_class;
1865extern const struct sched_class rt_sched_class;
1866extern const struct sched_class fair_sched_class;
1867extern const struct sched_class idle_sched_class;
1868
1851 ~ 1855 通过 链接 脚本中的 __begin_sched_class ; __end_sched_class
得到优先级最高的 调度器 sched_class_highest ; 优先级最低的调度去 sched_class_lowest
1860 的 for each sched class 就是从 highest 来时遍历的
kernel/sched/core.c 中,查找下一个 将要运行task 的函数, pick_next_task
4362 ~ 4364 - 从 highest sched class 找的,找到就返回,找不到才使用 低优先级的 sched class
4327/*
4328 * Pick up the highest-prio task:
4329 */
4330static inline struct task_struct *
4331pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
4332{
4361 for_each_class(class) {
4362 p = class->pick_next_task(rq);
4363 if (p)
4364 return p;
4365 }
4369}
include\asm-generic\vmlinux.lds.h 中对 各个调度器 对象 进行了排序
127 */
128#define SCHED_DATA \
129 STRUCT_ALIGN(); \
130 __begin_sched_classes = .; \
131 *(__idle_sched_class) \
132 *(__fair_sched_class) \
133 *(__rt_sched_class) \
134 *(__dl_sched_class) \
135 *(__stop_sched_class) \
136 __end_sched_classes = .;
以 fair_sched_class 为例: 定义在 kernel/sched/fair.c#L254
注意,里面的 __section 说明,将这个结构体都放在了 __fait_sched_class 这个 section 里面; 上面的 vmlinux.lds.h 中才使用这个 section
11179/*
11180 * All the scheduling class methods:
11181 */
11182const struct sched_class fair_sched_class
11183 __section("__fair_sched_class") = {
11184 .enqueue_task = enqueue_task_fair,
11185 .dequeue_task = dequeue_task_fair,
11186 .yield_task = yield_task_fair,
11187 .yield_to_task = yield_to_task_fair,
11188
11189 .check_preempt_curr = check_preempt_wakeup,
11190
11191 .pick_next_task = __pick_next_task_fair,
11192 .put_prev_task = put_prev_task_fair,
11193 .set_next_task = set_next_task_fair,