Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

时间片与优先级调度

复习

  • 上下文切换:保存一个进程的现场,再恢复另一个
  • 调度要解决什么:响应、吞吐、公平和优先级之间的矛盾
  • 先来先服务与最短任务优先:简单调度为何会出现等待和饥饿

TL;DR

  • 时间片轮转:每个进程只跑一小段,时间一到就换人,保证人人有份
  • 时间片太小,切换开销大;太大,又退化成先来先服务
  • 优先级调度:重要的先跑,但低优先级可能被饿死
  • 老化:等得越久,临时提高优先级,防止长期挨饿

正文

  先来先服务和最短任务优先,一个太“死板”,一个太“理想”。现实中的系统,既想让交互程序快速响应,又想让重要任务优先完成。于是有了两种更实用的思路:切小片轮着跑,以及按重要性排座次。

时间片轮转

  时间片轮转(RR,Round Robin)的做法是:给每个进程一小段时间,叫一个时间片(time slice),让它跑;时间一到,无论跑没跑完,都强制换下一个,自己回到就绪队列的队尾。

A 跑一个片 │ B 跑一个片 │ C 跑一个片 │ A 再跑一个片 │ ……

  这样,每个进程最多等“队伍长度 × 时间片”的时间,就能轮到自己。交互程序要的“响应快”,靠它来保证。

  时间片的大小很有讲究:

  • :进程还没干多少活就被换下,切换开销占比变大,吞吐下降
  • :一个进程又要等很久才轮到,退化成先来先服务,响应变差

  所以时间片要取一个折中值——通常远大于一次上下文切换的开销,又不至于让人明显感到卡顿。

优先级调度

  可有些进程就是更“要紧”:负责接收用户输入的、负责网络通信的、系统的关键进程……时间片轮转一视同仁,对它们不够友好。

  于是有了优先级调度:给每个进程一个优先级,优先级高的先上 CPU。同优先级之间,可以再用时间片轮转。

  优先级有两种来路:

  • 静态:一开始定好,运行中不变
  • 动态:根据情况调整,比如刚用完 CPU 的降一点、刚等待完 I/O 的升一点

饥饿与老化

  优先级调度有个老毛病:低优先级的进程可能一直排不上队。只要高优先级的任务源源不断,低优先级的就会一直等下去,这叫饥饿(starvation)。

  解决办法叫老化(aging):进程等待的时间越长,就慢慢把它的优先级抬一点。等得够久,再低的优先级也能熬出头,最终被调度一次。这样一来,“分轻重”和“够公平”之间就有了一条折中的路。

现实里的组合

  真实的调度器,很少只用一种办法,而是把上面几招组合起来:优先级决定大致座次,时间片保证人人轮得到,老化兜住被冷落的进程。 调度的艺术,就在于把这些互相拉扯的目标,调到一个多数场景都满意的平衡点。

  到这里,调度的基本招式就讲完了。可有心的读者会问:如果系统里有成千上万个进程,一个个比较优先级是不是太慢?还有一个更聪明的“反馈”办法。下一章,我们看多级反馈队列——它连“任务大概要跑多久”都不用事先知道。

思考题

  时间片设成多大才合适?如果系统主要跑的是交互程序,你会倾向选大还是选小?如果主要跑的是批量计算任务呢?

小结

知识点

  • 时间片轮转:轮流跑一小段,保证响应
  • 时间片大小的权衡
  • 优先级调度:重要的先跑
  • 饥饿与老化
  • 现实调度常把优先级、时间片、老化组合使用

参考资料

  1. Wikipedia(zh):时间片:时间片轮转
  2. Wikipedia(zh):优先级调度:优先级与老化
  3. Wikipedia(zh):饥饿 (计算机科学):进程饥饿

思考题答案(仅供参考)

  时间片要足够大,能盖过一次上下文切换的开销,又不至于让等待的人明显感到卡顿。若主要跑交互程序,倾向选小一些:宁可多切换几次,也要让每次点击、按键都尽快有反应。若主要跑批量计算任务,倾向选大一些:这类程序对响应不敏感,少切换反而更省,吞吐更高。所以没有固定答案,要看系统主要面对什么样的负载。

协议

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

封面图

设计师 | 南国微雪