enqueue_task_rt
中的 ./kernel/sched/rt.c
函数负责将任务排队到运行队列。 enqueue_task_rt
包含致电enqueue_rt_entity
的{{1}}来电。代码的大部分内容看似合乎逻辑,但由于函数dequeue_rt_stack
无法理解它的作用,我有点迷失。有人能说出我错过的逻辑是什么,或者建议一些好读。
编辑:以下是dequeue_rt_stack
功能
dequeue_rt_stack
更具体地说,我不明白为什么需要这个代码:
struct sched_rt_entity *back = NULL;
/* macro for_each_sched_rt_entity defined as
for(; rt_se; rt_se = rt_se->parent)*/
for_each_sched_rt_entity(rt_se) {
rt_se->back = back;
back = rt_se;
}
for (rt_se = back; rt_se; rt_se = rt_se->back) {
if (on_rt_rq(rt_se))
__dequeue_rt_entity(rt_se);
}
它的相关性是什么。
答案 0 :(得分:2)
当要将某个任务添加到某个队列时,必须先将其从当前所在的队列中删除(如果有)。
使用group scheduler,任务始终位于树的最低级别,并且可能有多个祖先:
NULL
^
|
+-----parent------+
| |
| top-level group |
| |
+-----------------+
^ ^_____________
| \
+-----parent------+ +-----parent------+
| | | |
| mid-level group | | other group | ...
| | | |
+-----------------+ +-----------------+
^ ^_____________
| \
+-----parent------+ +-----------------+
| | | |
| task | | other task | ...
| | | |
+-----------------+ +-----------------+
要从树中删除任务,必须从所有组的队列中删除该任务,这必须首先在顶级组中完成(否则,调度程序可能会尝试运行已部分删除的任务)。因此,dequeue_rt_stack
使用back
指针构建相反方向的列表:
NULL back
^ |
| V
+-parent----------+
| |
| top-level group |
| |
+----------back---+
^ | ^_____________
| V \
+-parent----------+ +-----parent------+
| | | |
| mid-level group | | other group | ...
| | | |
+----------back---+ +-----------------+
^ | ^_____________
| V \
+-parent----------+ +-----------------+
| | | |
| task | | other task | ...
| | | |
+----------back---+ +-----------------+
|
V
NULL
然后可以使用back
列表向下走树以按正确顺序删除实体。
答案 1 :(得分:1)
我是内核黑客的新手。这是我第一次回答linux内核问题。 也许这对你有帮助。
我阅读了源代码。我认为这可能与小组安排有关。
当内核有这些代码时:
#ifdef CONFIG_RT_GROUP_SCHED
它表示我们可以将一些计划实体收集到一个schduling组中。
static void enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
{
dequeue_rt_stack(rt_se);
for_each_sched_rt_entity(rt_se)
__enqueue_rt_entity(rt_se, head);
}
函数dequeue_rt_stack(rt_se)提取属于该组的所有调度实体,然后将它们添加到运行队列中。