我是 Linux 内核的初学者,我正在尝试学习 Linux 如何调度进程。
我已经阅读了一些关于 Linux 内核的书籍并浏览了来自 IBM 的链接 http://www.ibm.com/developerworks/linux/library/l-cfs/和所有,但我仍然有一些疑问。
- 调度程序如何在
sysctl_sched_latency
时间内安排所有任务? - 当进程唤醒时,
place_entity
函数中实际做了什么? - 当进程唤醒时,为什么要通过从
sched_latency
中减去来调整vruntime
?这不会导致运行队列中的进程在vruntime
值上有很大差异吗?
最佳答案
首先是任务的虚拟运行时间
- 理论上是任务开始下一个时间片的时间 在理论上完美的多线程 CPU 上执行。
- 在实践中是将其实际运行时间归一化为正在运行的任务总数
<强>1。调度器如何调度所有的任务在 sysctl_sched_latency 时间?
它维护了一个时间有序的红黑树,所有可运行的任务都在树上 按它们的虚拟运行时排序。左侧的节点运行时间最短。 CFS 选择最左边的任务并运行它,直到任务调度或调度程序滴答作响 然后它运行的 CPU 时间被添加到它的虚拟运行时。 当它不再是最左边的节点时,运行具有最短虚拟的新任务并且 旧任务已启动。
<强>2。当进程唤醒时,place_entity 函数中实际做了什么?
简短版:
当进程唤醒时,place_entity 函数要么离开 任务的虚拟运行时原样或增加它。
长版:
当进程唤醒时,place_entity 函数会做以下事情
将临时虚拟运行时初始化为 CFS 运行队列的最小任务的虚拟运行时。
由于 sleep 少于一个延迟不算数, 将阈值变量初始化为 sysctl_sched_latency。 如果启用了 GENTLE_FAIR_SLEEPERS 功能, 然后将 this 变量的值减半。 将先前初始化的临时虚拟运行时减去此阈值。
通过将计算出的虚拟运行时间设置为自身和任务虚拟运行时间的最大值,确保临时虚拟运行时间至少等于任务的虚拟运行时间。
将任务的虚拟运行时设置为临时运行时。
<强>3。当进程唤醒时,为什么要通过从 sched_latency 中减去来调整 vruntime?
虚拟运行时间递减,因为 sleep 少于一个延迟不算数。 例如,任务不应该改变它在红黑树中的位置,如果它有 只睡了一个调度程序延迟。
<强>4。这不会导致运行队列中的进程在 vruntime 值上存在较大差异吗?
我相信问题 2 的步骤 3 中描述的逻辑可以防止或至少最大限度地减少这种情况。
引用资料
关于Linux CFS(完全公平调度程序)延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8016154/