2.3.6 O(1)调度器 - 时间分配
每个调度周期结束后需要单独为每个任务分配时间,效率底下。为了解决这个问题,O(1)调度器为每个runqueue准备了两个任务列表,对应的字段为 prio_array_t *active, *expired, arrays[2];
其中 active
用来存放就绪任务,而 expired
用来存放时间片已经耗尽的任务。在调度时,调度器使用 active
来寻找下一个任务,这在前文中我们探讨调度逻辑时已经看到了,而当任务的运行时间被耗尽后,系统会立刻为其计算下一轮的运行时间并将其放入 expired
列表,这样当 active
为空时,调度器就不用暂停所有工作来分配时间,而是直接切换 active
与 expired
两个列表即可。该逻辑发生在调度函数 schedule()
中:
这段代码就在前面主调度逻辑之前。系统在时钟中断函数中会检查任务的运行时间,如果时间耗尽则会为其重新充值,并考虑是否放入 expired
列表中。这段逻辑在函数 schedule_tick()
中:
如果任务被扔到expired列表,那么它在这一轮周期内就没有机会再运行了,但对于交互式任务而言可能导致响应延迟,造成不好的用户体验,因此我们希望尽可能地不要将交互式任务从active中剔除,系统通过宏 TASK_INTERACTIVE
来判断任务是否是交互式任务,主要判断依据是任务的平均睡眠时间。但也要避免交互式任务一直呆在active里面导致expired中的任务被饿死,所以系统会使用宏 EXPIRED_STARVING
来判断expired列表中的任务是否要饿死了,如果是的话,那么依然会将任务扔进expired中,乖乖地等待下一轮调度。
计算任务时间片的函数是 task_timeslice
, O(1)计算时间片时与CPU的频率无关,只根据任务的静态优先级计算出一个确定的时间片。由于O(1)在调度时已经奖励过交互式任务,因此这里的逻辑就简单了,这里不再深入讨论。
Last updated