进程调度算法
当有两个或更多的进程处于就绪状态,如果只有一个 CPU 可用,那么就必须要选择下一个要运行的进程。在操作系统中,完成选择的这一部分称为调度程序(scheduler)。该程序使用的算法称为调度算法(scheduling algorithm)。
调度时机
什么时候会发生 CPU 调度呢?通常有以下情况:
- 在创建一个新进程后,需要决定是运行父进程还是运行子进程
- 此时两个进程都是就绪状态,可以任意决定
- 在一个进程退出时要选择下一个运行的进程
- 此时会在就绪程序中选择一个进程
- 当一个进程阻塞在 I/O、信号量或由于其他原因阻塞时,要选择另一个进程运行
- 此时会在就绪程序中选择一个进程,有时阻塞的原因会成为选择的原因
- 比如,A 进程是一个重要的进程,并正在等待 B 退出临界区,让 B 随后运行会是个很好的选择,可惜调度程序并不知道这些信息
- 此时会在就绪程序中选择一个进程,有时阻塞的原因会成为选择的原因
- 在一个 I/O 中断时,必须要选择下一个运行的程序
- 如果中断来自 I/O 设备,而该设备现在完成了任务,等待该 I/O 的进程就变成就绪进程了
非抢占式调度:
非抢占式调度算法选择一个进程,然后让该进程运行直到阻塞(阻塞在 I/O 或等待另一个进程),或者直到该进程自动释放 CPU。即使该进程运行了若干小时,它也不会被挂起。
抢占式调度:
抢占式调度算法选择一个进程,并且让该进程运行某个固定时段的最大值。如果在该时段结束时,该程序仍在运行,它将被挂起,而调度程序选择另一个进程运行(如果存在另一个就绪进程)。
先来先服务算法
在所有调度算法中,最简单的是非抢占式的先来先服务(first-come first-served, FCFS)算法。
顾名思义,就是选择最早进入就绪队列的进程,然后运行该进程,直到该进程被阻塞或运行结束,才会继续在就绪队列中选择下一个进程运行。
这似乎很公平,不过 FCFS 也有很明显的缺点,当一个长作业运行时,后续的短作业等待时间会很长。
FCFS 适合计算密集型作业,不适合 I/O 密集型作业。
最短作业优先算法
最短作业优先(shortest job first, SJF)算法也是一种非抢占式算法。同样顾名思义,它会优先选择运行时间最短的进程来运行。
这种算法同样有明显的缺点,如果一个作业的运行时间特别长,而系统不断产生短作业,那么它可能很久都不会被调度。
最短剩余作业优先算法
最短作业优先算法的抢占式版本是最短剩余作业优先(shortest remaining time first, SRTF)算法。顾名思义,它会优先选择剩余运行时间最短的进程来运行。
轮转调度算法
一种最古老、最简单、最公平且使用最广泛的算法是轮转调度(round robin, RR)。
每个进程被分配一个时间段,称为时间片(quantum),即允许该程序在该时间段中运行。
- 如果在时间片结束时该程序还在运行,则将剥夺 CPU 并分配给另一个进程
- 如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换
时间片长度的设置是该算法的关键点:
- 时间片设得太短会导致过多的进程切换,降低了 CPU 效率
- 进程切换时需要保存上个未运行结束的进程的信息,同时要装入即将执行的进程的信息
- 时间片设得太长又可能导致对短的交互请求的响应时间变长
将时间片设为 20 ~ 50ms 通常是一个比较合理的折中。
优先级调度算法
轮转调度做了个隐含的假设,即所有的进程同等重要,而拥有和操作多用户计算机系统的人对此有不同的看法。他们希望调度是有优先级的,即希望调度程序能从就绪队列中选择最高优先级的进程运行,这称为优先级调度算法。其基本思想也很清楚:每个进程被赋予一个优先级,允许优先级最高的可运行进程先运行。
该算法也有两种处理优先级高的方法,非抢占式和抢占式:
- 非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程
- 抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行
但是依然有明显缺点,可能会导致低优先级的进程永远不会运行。
多级队列调度算法
多级队列调度(compatible time sharing systime, CTSS)算法是轮转算法和优先级调度算法的结合与发展。
工作流程:
- 设置多级队列,每个队列的优先级不同,优先级越高的队列分到的时间片越短
- 新的进程到来时会被放到最高优先级的队尾,按先来先服务原则排队等待调度,如果时间片结束还没运行完,就把该进程放到下一级队列的队尾
- 当较高级队列为空时,才会调度较低级队列的进程。在较低优先级的队列中的进程在运行时,又有新到达的作业,此时须立即把正在运行的进程放回当前队列的队尾,然后调度高优先级进程
彩票调度算法
有一个既可以给出类似预测结果而又非常简单的算法,彩票调度(lottery scheduling)算法。
其基本思想是为每个进程提供各种系统资源的彩票。一旦需要做出一项决策时,就随机抽出一张彩票,拥有该彩票的进程获得该资源。
为了说明 George Orwell 关于「所有进程是平等的,但是某些进程更平等一些」的含义,可以给更重要的进程额外的彩票,以便增加它们获胜的机会。如果出售了 1230 张彩票,而有一个进程持有其中的 123 张,那么在每一次抽奖中该进程就有 10% 的取胜机会。在较长的运行中,该进程就会得到 10% 的 CPU。