操作系统:CPU调度

来源:互联网 发布:淘宝的观复博物馆 编辑:程序博客网 时间:2024/06/05 04:41

前面我们已经总结了process的一些基本信息,进程是程序运行的一个基本单位。当进程运行的时候,需要占用CPU,如果当多个进程需要运行的时候,我们该怎么安排这些进程占用CPU呢? 这就是我今天要总结的CPU调度

在正式讨论CPU调度策略之前,我们先来看看CPU调度我们会考虑哪几个方面的因素:

  • turnaround时间(周转时间):任务完成时间 - 任务到达时间
  • 响应时间:任务开始运行时间 - 任务到达时间
  • 公平性
  • 整体性能

在介绍每一种CPU调度策略之后,我会从这四个方面来分析调度策略的优点和缺点;

FIFO(First In, First Out)

多个任务都需要使用CPU这个场景很像在路边小吃摊排队的场景,自然而然可以想到谁先来,谁就先被服务。这就是所谓First In, First Out; 也叫First come, First served.
这种调度策略实现起来相对简单,但在某些方面表现却不是十分友好:

假设有三个任务A、B、C同时到达(at time 0),需要运行的时间为1000ms,20ms,20ms。这个时候先执行A,再执行任务B,最后执行任务C;

在这种情况下,任务B和C各自只是用CPU时间20ms,却要等上1000ms。一旦先来运行的是个耗时比较长的任务,那后面到来耗时短的任务需要等待很长时间才能上CPU运行;这种策略对耗时较短任务不友好
那我们改变现有的策略,让耗时短的任务先运行,看看怎么样。

短作业优先(shortest job first)

在这种模式先,在上面描述的场景就可以完美解决了:任务B和C先被执行,最后完成任务A;这种情况下符合我们预期;但修改一些任务到达的条件,又是怎么样呢?

假设任务A、B、C耗时分别是1000ms, 20ms, 20ms, 但A先到达,B和C在A到达10ms之后到达;

这种情况下,又出现了如FIFO中描述的问题,B和C依旧需要等待990ms、1010ms的时间才能运行;
这个时候就考虑能不能让耗时短的任务抢占CPU呢?(抢占CPU需要消耗资源),于是乎有了Shortest Time-to-Completion First(STCF)

抢占式短作业优先(Shortest Time-to-Completion First)

对于上面描述的场景,在这种场景下,任务B上来就可以运行,任务C等待20ms可以运行,然后任务A继续接着运行(没有考虑上下文切换耗时)。如果仅仅考虑turnaround time,现在的这种方法已经足够了;

但如果考虑每个任务的响应时间呢?
以上的三种调度策略都需要等待某个任务完成,才能开始运行,这样会导致任务的平均响应时间变大,那么有没有方式,使任务的平均响应时间变短呢?这就是想到Round Robin策略了

Round Robin

在这种策略下,不再是把任务运行完之后再运行下一个任务,取而代之的是每个任务轮流在CPU上运行一个时间片。
这样的好处是,在任务到达之后,等待几个较短的时间片之后,新来的任务就可以开始运行了。这样降低了任务的响应时间。

一下两点值得我们注意:

  • Round Robin策略对每个任务来说都是公平的,同时降低了任务的响应时间,但与此同时确是增加了平均的turnaround time却是增加的。这是trade-off,具体选用那种策略,在于我们更关注哪个方面的表现
  • 实现RR策略,每一个时间片用完,都需要进行上下文切换的。进行上下文切换的消耗会均摊到所有执行的任务上

我们知道,内核的进程比用户进程优先级高;对于同样的内核进程和同样的用户进程,他们也有优先级区别,在CPU调度上,我们如何体现出任务的优先级呢?

多级反馈队列Multi-Level Feedback Queue

为了RR调度策略的turnaround time和降低交互任务的响应时间,于是就有了多级反馈队列调度策略;操作系统的大多使用该算法进行CPU调度;
多级反馈队列示意图
对于上面的多级反馈队列的数据结构的简单示例,从下到上优先级依次增加。
在这个多级反馈队列中,调度过程需要遵循如下有如下几条规则:

  1. 如果任务A的优先级大于任务C的优先级,则先运行任务A
  2. 任务A和B优先级一样,则任务A、B以Round Robin的方式运行
  3. 当有新任务到来的时候,进入优先级最高的队列
  4. 一旦一个任务用完了时间片或者因为I/O放弃了CPU,则将该任务移到下一个优先级队列
  5. 固定周期之后,把所有的任务都迁移到优先级最高的队列中去