文章目录
- 一、rt_sched_class 结构体变量类型 sched_class
- 二、next 字段值
- 三、enqueue_task 函数指针值
- 四、dequeue_task 函数指针值
- 五、yield_task 函数指针值
- 六、pick_next_task_rt 函数
- 七、pick_next_task_rt 函数
一、rt_sched_class 结构体变量类型 sched_class
在 【Linux 内核】实时调度类 ③ ( 实时调度类 rt_sched_class 源码 | 调度类 sched_class 源码 ) 博客中 , 简单介绍了 实时调度类 rt_sched_class
结构体 , 下面开始分析该结构体的具体字段含义 ,
该 rt_sched_class
结构体 在 Linux 内核源码的 linux-5.6.18kernelschedrt.c
源文件中定义 ;
const struct sched_class rt_sched_class = {
.next = &fair_sched_class,
.enqueue_task = enqueue_task_rt,
.dequeue_task = dequeue_task_rt,
.yield_task = yield_task_rt,
.check_preempt_curr = check_preempt_curr_rt,
.pick_next_task = pick_next_task_rt,
.put_prev_task = put_prev_task_rt,
.set_next_task = set_next_task_rt,
#ifdef CONFIG_SMP
.balance = balance_rt,
.select_task_rq = select_task_rq_rt,
.set_cpus_allowed = set_cpus_allowed_common,
.rq_online = rq_online_rt,
.rq_offline = rq_offline_rt,
.task_woken = task_woken_rt,
.switched_from = switched_from_rt,
#endif
.task_tick = task_tick_rt,
.get_rr_interval = get_rr_interval_rt,
.prio_changed = prio_changed_rt,
.switched_to = switched_to_rt,
.update_curr = update_curr_rt,
#ifdef CONFIG_UCLAMP_TASK
.uclamp_enabled = 1,
#endif
};
rt_sched_class
结构体变量 是 sched_class
结构体类型的 , 这是 调度类 类型 , 该结构体的 字段 和 函数指针 含义在
- 【Linux 内核】调度器 ② ( sched_class 调度类结构体源码 | 源码路径 linux-5.6.18kernelschedsched.h )
- 【Linux 内核】调度器 ③ ( sched_class 调度类结构体分析 | next 字段 | enqueue_task 函数 | dequeue_task 函数 )
- 【Linux 内核】调度器 ④ ( sched_class 调度类结构体分析 | yield_task 函数 | heck_preempt_curr 函数 | task_struct 函数 )
- 【Linux 内核】调度器 ⑤ ( put_prev_task、set_next_task 函数 | select_task_rq 函数 | migrate_task_rq 函数 )
- 【Linux 内核】调度器 ⑥ ( task_woken 函数 | set_cpus_allowed 函数 | rq_online 函数 | rq_offline 函数 )
博客中 , 有详细的介绍 ;
二、next 字段值
Linux 系统中的 " 调度类 " 链表中 , 下一个 " 调度类 " 指针 , 指向一个 公平调度类 地址 ;
代码语言:javascript复制.next = &fair_sched_class,
参考资料 : 【Linux 内核】调度器 ③ ( sched_class 调度类结构体分析 | next 字段 | enqueue_task 函数 | dequeue_task 函数 )
整个 Linux 系统中有 多个 " 调度类 " , 按照 优先级进行排序 , 这些 " 调度类 " 放在一个 " 链表 " 中 , 优先级高的 " 调度类 " 先执行 , 优先级低的后执行 ;
sched_class
调度类结构体 中的 next
字段 , 就是指向 " 调度类 " 链表 中的 下一个 " 调度类 " ; ( 优先级低于本调度类 )
const struct sched_class *next;
源码路径 : linux-5.6.18kernelschedsched.h#1709 ;
三、enqueue_task 函数指针值
将一个 task 任务 enqueue_task_rt
, 存放到 " 执行队列 " ( 红黑树 ) 的 " 尾部 " ( 最右侧 ) ;
.enqueue_task = enqueue_task_rt,
enqueue_task_rt 函数如下 :
代码语言:javascript复制static void
enqueue_task_rt(struct rq *rq, struct task_struct *p, int flags)
{
struct sched_rt_entity *rt_se = &p->rt;
if (flags & ENQUEUE_WAKEUP)
rt_se->timeout = 0;
enqueue_rt_entity(rt_se, flags);
if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
enqueue_pushable_task(rq, p);
}
参考资料 : 【Linux 内核】调度器 ③ ( sched_class 调度类结构体分析 | next 字段 | enqueue_task 函数 | dequeue_task 函数 )
sched_class
调度类结构体 中的 enqueue_task
函数指针 , 指向一个函数 , 调用该函数 , 可以将 " 进程 " 加入到 " 执行队列 " 中 , 同时 nr_running
自增
;
- 进程 是一个 调度实体 ;
- 执行队列 是一个 红黑树 ;
void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
源码路径 : linux-5.6.18kernelschedsched.h#1715 ;
四、dequeue_task 函数指针值
将一个 task 任务 dequeue_task_rt
, 从 " 执行队列 " ( 红黑树 ) 的 " 尾部 " ( 最右侧 ) 移除 ;
.dequeue_task = dequeue_task_rt,
dequeue_task_rt 函数如下 :
代码语言:javascript复制static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int flags)
{
struct sched_rt_entity *rt_se = &p->rt;
update_curr_rt(rq);
dequeue_rt_entity(rt_se, flags);
dequeue_pushable_task(rq, p);
}
参考资料 : 【Linux 内核】调度器 ③ ( sched_class 调度类结构体分析 | next 字段 | enqueue_task 函数 | dequeue_task 函数 )
dequeue_task
调度类结构体 中的 dequeue_task
函数指针 , 指向一个函数 , 调用该函数 , 可以 从 " 执行队列 " 中删除 " 进程 " , 同时 nr_running
自减
;
- 进程 是一个 调度实体 ;
- 执行队列 是一个 红黑树 ;
void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
源码路径 : linux-5.6.18kernelschedsched.h#1716 ;
五、yield_task 函数指针值
调用该 yield_task_rt
函数指针 指向的 函数 , 主动放弃执行 ;
.yield_task = yield_task_rt,
yield_task_rt 函数如下 :
代码语言:javascript复制static void yield_task_rt(struct rq *rq)
{
requeue_task_rt(rq, rq->curr, 0);
}
参考资料 : 【Linux 内核】调度器 ④ ( sched_class 调度类结构体分析 | yield_task 函数 | heck_preempt_curr 函数 | task_struct 函数 )
sched_class
调度类结构体 中的 yield_task
函数指针 , 指向一个函数 , 调用该函数 , 该 " 进程 " 将 放弃 已分配的 CPU 时间片 的 执行权限 , 先将进程从 " 执行队列 " 中出队 , 然后再 放入到队列末尾 ;
- 进程 是一个 调度实体 ;
- 执行队列 是一个 红黑树 ;
也就是说 调用该函数 , 将 调度实体 ( 进程 ) 存放到了 红黑树 ( 执行队列 ) 的 最右端 ( 末尾 ) ;
代码语言:javascript复制void (*yield_task) (struct rq *rq);
源码路径 : linux-5.6.18kernelschedsched.h#1717 ;
六、pick_next_task_rt 函数
调用 pick_next_task_rt
函数 , 选择 " 执行队列 " ( 红黑树 ) 中将要被调度的任务 ;
.pick_next_task = pick_next_task_rt,
pick_next_task_rt 函数如下 :
代码语言:javascript复制static struct task_struct *pick_next_task_rt(struct rq *rq)
{
struct task_struct *p;
if (!sched_rt_runnable(rq))
return NULL;
p = _pick_next_task_rt(rq);
set_next_task_rt(rq, p, true);
return p;
}
七、pick_next_task_rt 函数
调用 put_prev_task_rt
函数 , 选择 " 执行队列 " ( 红黑树 ) 中将要被调度出执行的任务 , 其返回值是将要被调度的任务 ;
.put_prev_task = put_prev_task_rt,
put_prev_task_rt 函数如下 :
代码语言:javascript复制static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
{
update_curr_rt(rq);
update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 1);
/*
* The previous task needs to be made eligible for pushing
* if it is still active
*/
if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1)
enqueue_pushable_task(rq, p);
}