Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

多级反馈队列

本章为进阶内容,零基础读者可以跳过,不影响后续阅读。

复习

  • 调度要解决什么:响应、吞吐、公平和优先级之间的矛盾
  • 先来先服务与最短任务优先:简单调度为何会出现等待和饥饿
  • 时间片与优先级调度:让多个程序都感觉自己被及时响应

TL;DR

  • 多级反馈队列用多个优先级队列,让进程“先高后低”地浮动
  • 新进程从高优先级开始,用完时间片还没完,就降到下一级
  • 短任务在高优先级迅速完成,长任务逐级下沉,不必事先知道长短
  • 它是“自动适应任务长短”的一种巧妙设计

正文

  前面几种调度,要么要求“知道任务要跑多久”,要么需要人手工设定优先级。可现实中,调度器往往两眼一抹黑:来的到底是几毫秒的小任务,还是几小时的大家伙?

  多级反馈队列(MLFQ,Multi-Level Feedback Queue)就是为这种“未知”而生的。

多个队列,先高后低

  MLFQ 设置多个就绪队列,每个队列有不同的优先级:

高优先级  Q0  ← 新进程从这里开始
         Q1
         Q2
低优先级  Q3

  规则大致是这样的:

  • 新进程先进入最高优先级的队列
  • 同一队列内,用时间片轮转
  • 一个进程用完自己的时间片还没结束,就降到下一级队列
  • 只有高优先级队列空了,才轮到低优先级队列

它为什么聪明

  这套规则的效果很妙:

  • 短任务:一上来就在高优先级,往往一两个时间片就跑完了,很快离开系统
  • 长任务:占用 CPU 的时间越来越长,于是逐级下沉,把高优先级让给新来的短任务
  • 交互任务:经常等 I/O、很少用满时间片,于是能一直待在较高优先级,保持响应

  换句话说,它不用事先知道任务的长短,而是通过“观察它用了多少 CPU”来推断:总是很快就让出 CPU 的,多半是短任务或交互任务,给它高优先级;一直霸着 CPU 的,多半是长任务,把它压下去。

别忘了老化

  不过,如果高优先级源源不断地来新任务,长任务会被一直压在最底层,又出现饥饿。所以 MLFQ 通常还要配一条老化规则:低优先级队列里的进程,等得够久,就把它升回高一级;或者定期把所有进程都提到最高优先级,重新洗一次牌。

一句话总结

  MLFQ 把“优先级”变成了一个动态的、会自我调整的东西:谁表现得像短任务,谁就享受高优先级;谁表现得像长任务,谁就退居二线。它不需要预知,也不需要人工调参,是许多真实操作系统调度器的思想来源。

思考题

  一个交互程序,每跑一小会儿就要等一次键盘输入;另一个是长时间计算的任务。它们在 MLFQ 里,大致会分别停在哪一级?为什么?

小结

知识点

  • 多级反馈队列:多个优先级队列
  • 新进程从高优先级开始,用满时间片则降级
  • 通过“用 CPU 多少”间接推断任务长短
  • 需要老化来防止长任务饥饿

参考资料

  1. Wikipedia(zh):多级反馈队列:MLFQ
  2. Wikipedia(zh):调度_(计算):调度算法综述

思考题答案(仅供参考)

  交互程序会在较高优先级。因为它经常等待输入,很少用满时间片,不会被降级;而每次等待结束、重新就绪时,又往往能排到靠前的位置。长时间计算任务则会逐渐沉到较低优先级,因为它总是用满时间片、被一次次降级。只有当高优先级没有别的任务、或老化机制把它提上来时,长任务才会重新获得较高优先级。这正是 MLFQ “按表现分配优先级”的体现。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪