正如所解释的一些(有点旧)文章、Linux空闲任务(PID=0,每个 CPU 一个)在没有其他任务要运行时运行。为了让调度程序执行此操作,空闲任务必须为其保留最低优先级。链接的 LWN 文章中的旧文章Documentation/ftrace.txt
明确指出
prio“140”是为空闲任务保留的,它是最低优先级线程(pid 0)。
这是有道理的,但是在Linux 4.9下
# perf record -e sched:sched_switch sleep 1
# perf script
sleep 6526 [000] 362661.310842: sched:sched_switch: sleep:6526 [120] S ==> swapper/0:0 [120]
报告优先级为 120 swapper/0
(在右括号中),与上述内容相矛盾。
现在Linux调度程序是如何处理空闲任务的呢?提交更改ftrace.txt
(87d80de28,294ae4011)没有帮助。
答案1
我有一个不错的回答来自 Linux 内核邮件列表上的 Till Smejkal:
空闲任务有自己的调度类,仅处理每个 CPU 核心的空闲线程。该调度类在内核中可用的调度类中具有最低优先级。这意味着它是调度类列表中的最后一个,在任务切换时询问它们是否有要在 CPU 上调度的任务。因此,空闲任务不由 CFS 管理,因此没有任何好的值或优先级(或者至少现在不重要)。内核源代码中可能包含更多信息的有趣文件是
kernel/sched/idle_task.c
、kernel/sched/sched.h
和kernel/sched/core.c
。
然而,根据我的理解,任务可以有一个优先级,尽管不由 CFS 管理:实时任务 (SCHED_FIFO
和SCHED_RR
) 属于rt_sched_class
并且肯定具有有意义的优先级(根据 POSIX 的要求):
static inline int rt_policy(int policy)
{
return policy == SCHED_FIFO || policy == SCHED_RR;
}
但现在的重点是安排班级优先级,它是由以下结构实现的,这些结构通过它们的指针按此顺序const struct sched_class
链接:.next
stop_sched_class
dl_sched_class
rt_sched_class
fair_sched_class
idle_sched_class
该链表由 ( kernel/sched/sched.h
)遍历
#ifdef CONFIG_SMP
#define sched_class_highest (&stop_sched_class)
#else
#define sched_class_highest (&dl_sched_class)
#endif
#define for_each_class(class) \
for (class = sched_class_highest; class; class = class->next)
正如上面引用中提到的,pick_next_task()
要求kernel/sched/core.c
每个类提供一个可运行的任务,如下所示:
again:
for_each_class(class) {
p = class->pick_next_task(rq, prev, rf);
if (p) {
if (unlikely(p == RETRY_TASK))
goto again;
return p;
}
}
所有这些意味着空闲任务碰巧有一个优先级值(一些默认值),但在调度决策期间从不参考它,因为它们是idle_sched_class
.
上面的内容留下了更改优先级值的问题,但现在这主要具有历史意义(上面的代码引用来自 Linux 4.16)。