前言
上篇聊了基于周转时间的最短优先任务模型和基于响应时间的时间片轮转模型(3分钟,教你操作系统的任务调度思想(一) - 掘金 (juejin.cn))。
周转时间 = 任务完成时间 - 任务到达时间 响应时间:任务首次执行时间 - 任务到达时间
首先操作系统一方面保证短任务先执行,提高周转时间;同时要为用户提供良好的交互(比如用户做在屏幕前,等待进程响应),以提高响应时间。那操作系统究竟如何权衡? 还有操作系统如何知道哪些进程是短任务?
多级反馈队列给出了方案。
多级反馈队列 MLFQ
总体概念
MLFQ有多个队列,每个队列都有不同的优先级,操作系统先执行高优先级队列的任务;同一个队列里的多个任务则采用时间片轮转。 存储模型如图
规则
根据定义,多级反馈队列有两个规则,参考如上图
- 如果任务A的优先级高于B,执行A,不执行B
- 同一优先级,轮转执行。
基于这两个规则,缺点也很明显:由于A优先级高且执行时间过长,可能导致B,C,D永远无法获取CPU的执行权。
那就再加几个规则
- 任何任务到达时都进入到最高优先级队列,用完时间片后降低优先级
- 如果在任务执行的时间片内主动放弃CPU控制权,不会降级。(因为操作系统觉得这是类似交互型的任务,需要要较快的响应时间,需要优先执行)
接下来,举几个常见例子,演示多级反馈队列的工作原理
演示
长任务和短任务
一开始,系统来了一个交互任务A,把它放在最高优先级队列。由于交互任务在时间片内主动放弃CPU,所以它一直在最高优先级队列。
此时,系统来了一个长时间的任务B,由于B长工作,在自己时间片内B也没有主动放弃CPU,B最终降到最低级。这也符合最短完成时间优先的原则。如下图:
B的执行时间变化如下
假设交互型工作中有大量的 I/O 操作(比如等待用户的键盘或鼠标输入),它会在时间片用完之前放弃 CPU,不会降级。多级反馈队列就实现了让交互型工作的响应时间更好。
通过不同优先级队列以及降级策略,满足了最短完成时间优先的策略,也保证了同优先级的公平调度。
缺点
假设系统有太多的交互型工作,它们就会一直占用CPU,也就就导致叫低优先级的工作任务饿死。
其次,聪明的程序员可以编写代码愚弄调度程序,让程序每次在快用完时间片主动放弃CPU,这样它就永远占据CPU。
那就再加几个规则!!!
规则
- 每隔一段时间,所有任务都提到最高优先级队列
- 每个任务都有固定的时间份额。无论在时间片内是否放弃CPU。只要时间份额用完,任务会降低优先级。
规则5避免了 太多交互工作而导致最低优先级任务饿死的情况,如下图,黑色的任务一段时间后又回到最高优先级队列
规则6避免了调度程序被愚弄的情况,如下图
至此,完整的多级反馈队列模型出来了。完整的工作原理如下:
- 规则 1:如果 A 的优先级 > B 的优先级,运行 A(不运行 B)。
- 规则 2:如果 A 的优先级 = B 的优先级,轮转运行 A 和 B。
- 规则 3:工作进入系统时,放在最高优先级(最上层队列)。
- 规则 4:一旦工作用完了其在某一层中的时间配额(无论中间主动放弃了多少次CPU),就降低其优先级(移入低一级队列)。
- 规则 5 :经过一段时间 S,就将系统中所有工作重新加入最高优先级队列
总结
多级反馈有趣的原因是:它不需要对工作的运行方式有先验知识,而是通过观察工作的运行来给出对应的优先级。其中的核心思想就是预测:通过历史工作预测未来的行为。 预测思想计算机领域是很常见的
通过这种方式,MLFQ可以同时满足各种工作的需求:对于短时间运行的交互型工作,获得类似于SJF/STCF的很好的全局性能,同时对长时间运行的CPU密集型负载也可以公平地、不断地稳步向前。同时不同优先级队列可能设置不同的时间份额,协调长短任务。