程序管理-排程器 sched_class 結構體-fair_sched_class rt_sched_class 物件及優先順序
排程器 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, structtask_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)(structrq *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,