我正在研究 Linux 内核并试图弄清楚 Round Robin 调度算法的工作原理。在 kernel\sched_rt.c
文件中,有一个名为 task_tick_rt
的方法定义如下:
static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
{
update_curr_rt(rq);
watchdog(rq, p);
/*
* RR tasks need a special form of timeslice management.
* FIFO tasks have no timeslices.
*/
if (p->policy != SCHED_RR)
return;
if (--p->rt.time_slice)
return;
p->rt.time_slice = DEF_TIMESLICE;
/*
* Requeue to the end of queue if we are not the only element
* on the queue:
*/
if (p->rt.run_list.prev != p->rt.run_list.next) {
requeue_task_rt(rq, p, 0);
set_tsk_need_resched(p);
}
我不明白的(除了有一个无用的 queued
参数)是代码试图通过 if (--p->rt.time_slice )
检查。我不明白为什么任务列表指针 p
会减 1,换句话说,为什么方法检查的是 previous task 而不是当前任务?对此的任何澄清表示赞赏。
最佳答案
查看 c 运算符优先级 http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
->
运算符的优先级高于前缀 ++
,因此可以编写此特定条件:
if (--(p->rt.time_slice))
换句话说,递减的是时间片,而不是指针。
queued
参数在这里可能看起来毫无用处,但它存在是有原因的。特别注意从哪里调用 task_tick_rt()
。它唯一的引用是当它被分配给 struct sched_class
的 rt_sched_class
实例中的 .task_tick
函数指针时:
http://lxr.free-electrons.com/source/kernel/sched/rt.c#L1991
所以我们看到每个调度算法都有自己的 struct sched_class
函数 vector ,内核将调用它来调度服务。如果我们看看其他算法,我们会看到 CFS(完全公平调度)算法也有它自己的 struct sched_class
实例,名为 fair_sched_class
:
http://lxr.free-electrons.com/source/kernel/sched/fair.c#L6179
CFS案例中的.task_tick
成员指向task_tick_fair()
:
http://lxr.free-electrons.com/source/kernel/sched/fair.c#L5785
请注意 task_tick_fair()
是否 使用 queued
参数。因此,当调用 .task_tick
成员时(here 和 here),queued
参数将传入 0 或 1。因此,尽管 task_tick_rt()
不使用它,但 queued
参数必须仍然是它们的参数,因此 struct sched_class
函数 vector 中的函数指针类型全部匹配。
简而言之,struct sched_class
函数 vector 指定了调度算法与内核其余部分之间的接口(interface)。 queued
参数是应该给定的算法选择使用它,但在 Round Robin 的情况下,它被简单地忽略。
关于c - 了解 Linux 内核调度程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19327213/