2.3.2 O(n)调度器 - 时间分配
对普通任务而言,为了保证系统在时间分配上的公平性,O(n)调度器按照“轮”来计量调度周期,在每轮调度中,调度器根据各个任务的优先级为其分配时间,当所有任务的时间片都消耗完了之后,本轮度结束,系统开启下一轮调度。在 goodness()
中我们可以看到,如果一个普通任务已经没有了剩余时间,则会直接被忽略。
实时任务不受调度周期的限制,因为实时任务的高优先级最高,调度器要确保只要实时任务处于Ready状态,那么就立刻被调度到,本质上不存在预先分配时间的必须性。
调度器只是用运行时间来完成对
SCHED_RR
任务的轮询控制,函数schedule()
在遍历就绪队列之前存在如下逻辑:如果当前
SCHED_RR
任务的运行时间已经耗尽,则重新通过NICE_TO_TICKS(prev->nice)
重新为其分配时间,并将其移动到队列尾部,这样如果队列中有相同优先级的SCHED_RR
任务的话,本次就会被选中,从而达到轮询的目的。
如果在遍历队列时没有找到合适的任务,那么说明所有任务的运行时间都已经耗尽,本次调度周期已经结束了,调度器需要为任务分配时间、开启新的一轮调度周期。处理该逻辑的代码如下:
在下一轮调度周期中,任务的运行时间为 (p->counter >> 1) + NICE_TO_TICKS(p->nice);
, 这里涉及两个方面:
p->counter >> 1 上面遍历时不是没有找到合适的任务吗,那这里为何还要关心 p->counter 呢?因为上面遍历的是就绪队列(
runqueue_head
),所以调度器只是没有找到合适的就绪任务,而这里为任务分配时间片时,针对的是系统所有的任务。 此时系统中处于睡眠状态的任务就可能还有剩余时间,因此我们需要对这些任务的运行时间进行累积,让他们醒过来之后能够有更多的机会运行。为了避免此类任务的运行时间无限累积下去,每次都只累计一半的剩余时间。NICE_TO_TICKS
(p->nice) ticks 就代表着运行时间,宏NICE_TO_TICKS
根据任务的静态优先级(nice)为其分配运行时间。O(n)调度器的时间分配与CPU 频率也有关,具体逻辑如下:从直觉上来说,给任务分配时间应该只与优先级相关,与CPU的频率无关。系统做这种处理的目的是为了将运行时间根据CPU的频率做一个伸缩(scale), 否则如果一个低频CPU给每个任务分配的运行时间很长的话,就会导致一次调度周期很久都不会结束。
Last updated