操作系统入门 – CPU调度算法
在了解完进程和线程的概念后,我们就需要了解当一个进程就绪后系统会进行怎样的资源分配并运行进程,因此我们就需要了解CPU的调度算法
1.CPU调度
1.1概念
CPU调度即按照某种算法将CPU资源分配给某个就绪的进程。
1.2调度层次
- 高级调度(作业调度)
- 内存空间有限,可能无法将用户提交的全部作业放入内存,只能挑选一个或几个放入。
- 建立PCB,获得竞争权利。
- 每个作业只调入一次,调出一次。
- 作业调入时创建PCB,调出时释放PCB。
- 中级调度(内存调度)
- 为提高系统运行效率,将暂时不能执行的进程调出内存在外存中等待。
- 进程被调入外存后会进入挂起状态。
- 将数据段调入外存,而PCB则常驻内存。
- 一个进程可能会被多次调入调出。
- 低级调度(进程调度)
- 宏观层面上实现并发。
- 从就绪队列中选择一个进程并分配CPU资源。
- 调度频率很高。
层次 | 任务 | 调度 | 发生频率 | 进程及状态变化 |
---|---|---|---|---|
高级调度 | 调度处于后备队列中的作业,创建进程 | 外存->内存 | 最低 | 无->创建态->就绪态 |
中级调度 | 调度处于挂起队列中的进程 | 外存->内存 | 中等 | 就绪挂起->就绪/阻塞挂起->阻塞 |
低级调度 | 调度处于就绪队列中的进程 | 内存->CPU | 最频繁 | 就绪态->运行态 |
1.3 七种状态模型
七种状态模型就是上一篇文章所说的创建、就绪、执行、阻塞、终止以及就绪挂起和阻塞挂起七种状态。本节将会对就绪挂起状态和阻塞挂起状态进行重点介绍。
- 就绪挂起与就绪、阻塞挂起与阻塞,之间的状态可以相互转换。
- 当等待事件出现时“阻塞挂起”可以变为“就绪挂起”。
- PCB创建完成,无内存时,可以将进程调入外存成为“就绪挂起”。
- 当进程没有分配CPU资源时可以直接调入外存,此时由“运行”变为“就绪挂起”。
提示:判断进程是否被挂起可以查看进程是否被调入外存中。
2.进程调度的时机与方式
2.1 调度与切换
进程调度简单来说可以视为对某一个进程的选择,但其中包括了进程的选择和切换两个步骤,在切换过程中,需要对当前执行的进程进行上下文保存,并恢复下一个即将执行进程的数据并执行。
2.2调度的时机
2.2.1 主动放弃CPU
当任务执行完成、运行时发生异常以及进程主动进入阻塞状态时会主动放弃CPU。
2.2.2 被动放弃CPU
当 分给进程的时间片用完 或有更紧急的事情需要处理(I/O中断)、以及有其他更高优先级的进程进入就绪队列时,当前执行的进程会被动放弃CPU。
3.CPU调度算法
接下来讲解常见的几个CPU调度算法
3.1 先来先服务(FCFS)
该算法为非抢占式调度,选择就绪队列中等待时间最长的进程。进程按照进入就绪队列的先后顺序依次执行。
-
评价:系统开销小、对长进程有优势;更利于多CPU处理的进程
-
例子:在下图中可以看出,5个进程按时间先后依次进入就绪队列,因此系统按照进程的到达时间依次执行。
3.2 短作业优先(SJF)
短作业优先即选择下一个期望最短处理时间的进程运行。
3.2.1 抢占式SJF
进程主动离开CPU时调度运行时间最短的进程。即当新的进程执行所需时间小于当前进程执行所需的时间时,CPU就会执行那个后到的但执行时间更短的进程。
- 缺点:需要知道或估计进程会执行多长时间;可能史长进程产生饥饿;因为没有剥夺,所以不适合在实时系统中实现。
- 例子:P1先进入就绪队列,因而先执行P1。在P1执行过程中P2到达了,由于P2执行时间比P1长,因此P1并不会离开CPU而是继续执行。当P1运行结束后,就绪队列中只剩下P2,因此开始执行P2。在P2执行过程中P3到达,且P3预估执行时间比P2短,因此P2离开CPU,开始执行P3。此时P2剩余执行时间为5。到6时刻,P4进入就绪队列,P3运行时间还剩2,但P4执行时间大于P3,因此继续执行P3。8时刻P3运行结束,此时P5到达,在任务列中剩余P2、P4、P5,执行所需时间分别为5、5、2,因此先执行P5。当P5执行结束后按照先来先到的原则执行剩下的进程,也就是先执行P2,最后执行P4.
3.2.2 非抢占式SJF
非抢占式SJF即当运行进程主动放弃CPU控制权时的进程调度。
- 例子:0时刻P1到达,开始执行P1。当P1执行到2时刻时P2到达,此时依然执行P1。3时刻P1执行完毕,开始执行P2。从P2开始执行到结束的时间为12,此时P3、P4、P5陆续到达,但都处于等待执行状态。直到12时刻P2执行结束后,由于P5执行时间最短,因此先执行P5,随后按照进程执行长度依次执行P3和P4。
3.3优先级调度算法
每个进程有一个优先级,优先级由优先数来表示。优先级不同时调度优先权最高的进程,优先级相同时按照FCFS顺序调度。
3.3.1非抢占式
注:数字越小,优先级越高
- 例子:0时刻P1到达开始运行,2时刻P2到达,优先级比P1低,继续运行P1。P1运行结束后开始运行P2。由于P2运行时间较长,P3、P4、P5相继到达。此时P2未结束,但P5的优先级为当前所有进程最高,因此在P2运行完成后先运行P5,最后按优先级依次运行P3和P4。
3.3.2抢占式
新进程到达就绪队列是,若优先级比当前执行的进程高,则优先运行新进程。
3.4时间片轮转算法(RR)
时间片轮转算法会为每个执行的进程分配固定的执行时间,当时间一到则当前执行的进程将会转入就绪队列中,与此同时按照FCFS算法从就绪队列中取出新的进程执行。该调度算法也是目前主流操作系统使用的进程调度算法。
- 例子:假设系统的时间片为4,P1先到达,先执行P1。在执行过程中P2到达,由于P1执行时长为3,未使用完时间片,因此P1顺利完成并开始执行P2。在第二个时间片中,P3和P4先后到达。由于P2执行时间为6,大于时间片,因此在第7时刻时P2中断并进入就绪队列(此时P2未顺利完成),系统开始执行P3。在P3运行过程中P5到达。到11时刻时P3顺利完成,开始运行P4。由于P4运行时长超过时间片长度,因此在15时刻时P4中断。此时就绪队列中进程顺序为P2、P5、P4,三个进程执行时间小于时间片,按FCFS执行。
3.4多级队列调度
将就绪队列分为多个队列,每个队列都有不同优先级。当进程进入系统后根据具体情况如内存大小、优先级等分批进入不同队列中。队列之间使用优先级调度,同一队列使用自己的调度算法。
- 例子:前台交互优先级比后台批处理高,因此前台使用RR,后台使用FCFS。高优先级进程未运行完,低优先级进程无法运行,在低优先级进程运行时若高优先级进程到达,则可以抢占CPU。
4.总结
以下是各个算法的比较
调度算法 | 占用CPU方式 | 吞吐量 | 响应时间 | 开销 | 对进程影响 | 饥饿问题 |
---|---|---|---|---|---|---|
FCFS | 非抢占 | 不强调 | 可能很慢,尤其进程执行时间差别很大时 | 最小 | 短进程不利;I/O进程不利 | 无 |
RR | 抢占(时间片用完) | 时间片很小时吞吐量很低 | 为短进程提供很好响应时间 | 最小 | 公平对待 | 无 |
SJF | 非抢占 | 高 | 为短进程提供很好响应时间 | 可能较大 | 对长进程不利 | 可能 |
SRTN | 抢占(到达时) | 高 | 提供很好响应时间 | 可能较大 | 对长进程不利 | 可能 |
HRRN | 非抢占 | 高 | 提供很好响应时间 | 可能较大 | 很好的平衡 | 无 |
FeedBack | 抢占(时间片用完) | 不强调 | 不强调 | 可能较大 | 对I/O进程有利 | 可能 |