内核版本:linux 6.15.7

一、sched_class种类

按优先级,从高到低:STOP  >  RT   >  FAIR(cfs)  >  EXT(sched_ext)  >  IDLE

[root@hadoop02 linux-6.15.7]# grep -nr  "DEFINE_SCHED_CLASS"

kernel/sched/ext.c:4121:DEFINE_SCHED_CLASS(ext) = {

kernel/sched/deadline.c:3140:DEFINE_SCHED_CLASS(dl) = {

kernel/sched/rt.c:2613:DEFINE_SCHED_CLASS(rt) = {

kernel/sched/fair.c:13627:DEFINE_SCHED_CLASS(fair) = {

kernel/sched/idle.c:516:DEFINE_SCHED_CLASS(idle) = {

kernel/sched/stop_task.c:97:DEFINE_SCHED_CLASS(stop) = {

二、sched_class作用

sched_class(Scheduling Class)描述不同类别任务的调度逻辑,比如实时任务(RT),normal任务(FAIR等),struct sched_class提供一个通用模板,具体的调度器类需要实现其中的函数。

struct sched_class {

#ifdef CONFIG_UCLAMP_TASK
	int uclamp_enabled;
#endif

	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
	bool (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
	void (*yield_task)   (struct rq *rq);
	bool (*yield_to_task)(struct rq *rq, struct task_struct *p);

	void (*wakeup_preempt)(struct rq *rq, struct task_struct *p, int flags);

    ……

三、调度器类存在哪

调度器类按照优先级存在__sched_class_highest开始、以__sched_class_lowest结束的段中。

每个调度器类存在对应的xx_sched_class段中。

链接脚本vmlinux.lds.h控制了各个调度器类在段中的位置顺序,这个顺序决定了优先级关系。

__section("__" #name "_sched_class")定义了各调度器类存放的段名xx_sched_class。

kernel/sched/sched.h

#define DEFINE_SCHED_CLASS(name) \
const struct sched_class name##_sched_class \
	__aligned(__alignof__(struct sched_class)) \
	__section("__" #name "_sched_class")

__sched_class_highest和__sched_class_lowest两个变量是在vmlinux.lds.h中定义的,调度器类按照优先级存在__sched_class_highest开始的段中。

 kernel/sched/sched.c

/* Defined in include/asm-generic/vmlinux.lds.h */
extern struct sched_class __sched_class_highest[];
extern struct sched_class __sched_class_lowest[];

vmlinux.lds.h中决定了这些调度器类在段中的存放位置顺序。

include/asm-generic/vmlinux.lds.h

/*
 * The order of the sched class addresses are important, as they are
 * used to determine the order of the priority of each sched class in
 * relation to each other.
 */
#define SCHED_DATA                              \
        STRUCT_ALIGN();                         \
        __sched_class_highest = .;              \
        *(__stop_sched_class)                   \
        *(__dl_sched_class)                     \
        *(__rt_sched_class)                     \
        *(__fair_sched_class)                   \
        *(__ext_sched_class)                    \
        *(__idle_sched_class)                   \
        __sched_class_lowest = .;

四、调度器的遍历操作

kernel/sched/sched.h

#define for_each_class(class) \
	for_class_range(class, __sched_class_highest, __sched_class_lowest)

一个 task在任意时刻只能属于一个 sched_class,由struct task_struct->sched_class决定:

struct task_struct {

    const struct sched_class	*sched_class;

五、调度器类的函数集

以struct sched_class为模板,各个调度器类需要实现部分或全部函数接口,在代码中可以搜索关键字"DEFINE_SCHED_CLASS",以sched_ext调度器类为例:

DEFINE_SCHED_CLASS(ext) = {
	.enqueue_task		= enqueue_task_scx,
	.dequeue_task		= dequeue_task_scx,
	.yield_task		= yield_task_scx,
	.yield_to_task		= yield_to_task_scx,

	.wakeup_preempt		= wakeup_preempt_scx,

	.balance		= balance_scx,
	.pick_task		= pick_task_scx,

	.put_prev_task		= put_prev_task_scx,
	.set_next_task		= set_next_task_scx,

#ifdef CONFIG_SMP
	.select_task_rq		= select_task_rq_scx,
	.task_woken		= task_woken_scx,
	.set_cpus_allowed	= set_cpus_allowed_scx,

	.rq_online		= rq_online_scx,
	.rq_offline		= rq_offline_scx,
#endif

	.task_tick		= task_tick_scx,

	.switching_to		= switching_to_scx,
	.switched_from		= switched_from_scx,
	.switched_to		= switched_to_scx,
	.reweight_task		= reweight_task_scx,
	.prio_changed		= prio_changed_scx,

	.update_curr		= update_curr_scx,

#ifdef CONFIG_UCLAMP_TASK
	.uclamp_enabled		= 1,
#endif
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐