文章目录
C4 进程调度:介绍
上一节了解了底层机制(进程受限执行,上下文切换进程),接下来要搞清楚操作系统决定运行哪个进程的上层策略,即进程调度
4.1 工作负载假设
在探究进程调度策略之前,先做一些简化假设,这些假设与系统中运行的进程有关,有时称为工作负载,确认工作负载是构建调度策略的关键部分,负载了解的越多,策略就越优秀
对操作系统中运行的进程做出如下假设:
1,每一个工作运行相同的时间
2,所有工作同时到达
3,一旦开始,每个工作保持运行直到完成
4,所有工作只使用CPU
5,每个工作运行时间是已知的
这些假设大多是不现实的,但通过它们便于了解进程调度策略
4.2 调度指标:周转时间
除了工作负载外,还需要调度指标来比较不同的进程调度策略,在进程调度中,有一些不同的指标是有意义的
现在只使用一个指标周转时间,即:
周转时间 = 完成时间 - 到达时间
周转时间是一个性能指标,另一种指标是公平,性能和公平在调度系统中是矛盾的,如调度程序可以优化性能,但代价是阻止一些任务运行,这就降低了公平
4.3 先进先出 FIFO
一种最简单的调度策略即:先进先出 FIFO(先到先服务 FCFS)
FIFO有一些积极的特性,它很简单,且易于实现
先看一个例子:有任务A,任务B,任务C大致在相同的时间到达系统要求CPU服务,A比B早一点,B比C早一点,使用FIFO时会先去服务A,假设每个工作都运行10s,这3个工作的平均周转时间是多少?
A在0s进入CPU,10s结束,接着B在10s开始,20s结束,C在20s开始,30s结束,那么A的周转时间就是10-0=10s,B的周转时间是20-0=20s,C的周转时间是30-0=30s,平均周转时间60/3=20s
现在放宽假设1,每个进程的运行时间可以不同,同样是上述的模式,使用FIFO,但A运行需要100s,B和C运行需要10s,此时平均周转时间是(100+110+120)/3=110s

图7.2的问题称为护航效应,一些耗时较少的潜在资源消费者被排在了重量级的资源消费者之后。想象以下自己在超市买了一瓶水,排队结账时前面的人推了三个购物车
需要更好的算法处理任务实际运行时间不一样的场景
4.4 最短任务优先 SJF
最短任务优先(shorest job first),即先运行最短的任务,然后是次短的任务,如此下去
现在同样让A,B,C3个进程同时到达,A需要100s,B和C都需要10s,使用SJF策略时,先运行B©,再运行C(B),最后再运行最长的任务A,这样平均周转时间降低至了 (10+20+120)/3=50s,相比同条件的FIFO,要优秀的多
现在放宽假设2,每个任务可以随时到达,而不是同时到达,假设A在0s到达需要100s,B和C在10s到达,需要10s,那么SJF依旧会把A运行完后再处理B和C,这三项工作的平均周转时间是(100 + (110-10) + (120-10))=103

SJF在调度同时到达的任务时,有着不错的效果,但同时到达仅仅只是假设,当多个任务随机时间到达时,SJF仍然只能先运行完当前的任务,也有可能出现护航效应
需要更好的算法处理到达时间不同的场景
4.5 最短完成时间优先 STCF
SJF是一种非抢占式调度程序,所以当任务随机到达时会有护航效应,为了解决上述的问题,鉴于先前说过的时钟中断让操作系统恢复对CPU的控制权,和上下文机制切换进程,当A正在运行时,B和C到达时,使得调度程序可以抢占工作A,并决定运行另一个工作,稍后继续完成A
这样能抢占当前运行任务的调度程序即
STCF(shorest time-to-completion first),
即最短完成时间优先(抢占式最短作业优先),每当新工作进入系统时,它会确顶剩余工作和新工作中,谁的剩余时间最少,然后调度该工作,暂停当前的工作

因此在先前的例子中,STCF将抢占A并运行B和C以完成任务,当B和C完成后,再继续执行任务A,结果是平均周转时间提升了50%
如果多个运行时间不同的工作同时到达,SJF最优
如果多个运行时间不同的工作随机到达,STCF最优
4.6 新度量指标:响应时间
如果知道了任务长度,而且任务只使用CPU,唯一衡量的标准是周转时间时,STCF将是最好的调度策略,但引入分时系统改变了这一切,现在用户会坐在终端前要求系统良好的交互性,即较低的响应时间
响应时间的定义:
响应时间 = 首次运行时间 - 到达时间
同样是A,B,C这3个任务,A在0s时到达运行需要100s,B和C在10s时到达运行需要10s,采用STCF调度策略,A的响应时间为0-0=0,B的响应时间为10-10=0s,C的响应时间为20-10=10,其平均响应时间为3.33
采用STCF调度策略能保证良好的平均周转时间,但是如上一般三个任务需要执行时,第3个工作必须等待前两个工作都运行后才能运行,这种方法的响应时间是很糟糕的,假设你在终端运行某程序,不得不等待10s才能得到系统的响应,这是非常影响交互性的问题
因此除了考虑周转时间还要考虑响应时间,构建对响应时间敏感的调度程序
现在放宽假设3,每个任务不必一次全部执行完
4.7 轮转 RP
为了提高平均响应时间,采用轮转 RP(round robin)来进行调度,其基本思想为:RP在一个时间片内运行一个工作,然后切换到运行队列中的下一个任务,而不是把一个任务一次运行完,它反复执行,直到所有的任务都结束,因此RP也称为时间切片
时间片的长度必须是时钟中断的整数倍,如果时钟中断是每10ms中断一次,那么时间片是10ms,20ms,等时钟中断整数倍
假设任务A,B,C同时到达,且都需要5s运行,SJF和RP均需要15s来完成所有任务,但是SJF必须运行完当前任务才可以运行下一个任务,而采用1s的时间片,RP可以快速地循环工作

RP的平均响应时长是(0+1+2)/3=1,SJF的平均响应时长是(0+5+10)/3=5
时间片长度对RP是至关重要的,越短RP在响应时间上表现越好,但是过短的时间片也会产生问题,突然进行上下文切换的成本会影响整体的性能,短时间频繁的上下文切换降低系统性能
虽然使用RP进行调度可以获得较好的响应时间,但是计算上述示例的周转时长,A为13s,B为14s,C为15s,对于SJF有很大差距
但这也并不奇怪,如果周转时间是唯一标准,那么RP确实很糟糕,但RP保证了响应时间的快速,如果重视公平使用RP,那么周转时间不佳,如果重视性能,使用STCF,那么响应时间又会很差,这是不可兼得的
现在有两种调度程序,第一种(SJF,STCF)优化了周转时间,但对响应时间不利,第二种(RP)优化了响应时间,但对周转时间不利
4.8 结合I/O
现在放宽假设4,任务工作不但使用CPU,实际上几乎所有的任务都需要执行I/O,如果没有输入,它们但每次输出都是相同的,没有输出,看不到结果,这个任务就没有意义
调度程序需要工作在发起I/O时做出决定,因为当前运行的任务在使用I/O时,并不会使用CPU,它会被阻塞等待I/O完成,这时调度程序应该在CPU上安排另一项工作,且调度程序还需在I/O完成时做出决定
现在有两个工作A和B,都需要50ms的运行时间,但A每运行10ms,就需要进行10ms的I/O,而B只使用50ms的CPU,调度程序先运行A,再运行B,如果在A进行I/O时,CPU等待A那么就会浪费CPU的资源

一种常见的方法是将A的每10msCPU上的工作作为一个独立的工作,使用STCF,当A和B到达时,先运行10msA的子任务,然后运行B并进行A的I/O,然后提交A的下一个子任务,它抢占了B并运行10ms,这样就实现了重叠,一个进程在等待另一个进程的I/O完成时使用CPU,系统得到了更好的利用
这样的调度程序就结合了任务I/O,更好的利用了CPU
4.9 无法预知运行需要的时间
现在放宽最后一个假设,即不知道每个任务需要的时间
在一个通用操作系统中,操作系统对每个任务的长度知之甚少,不知道长度自然无法使用SJF,STCF,且还需要有良好的响应时间,应该使用哪种调度策略才能完成?
对于先前的5种假设,推翻考虑了4种,得到了两类方法
第一类即运行最短的工作,从而优化周转时间,第二类是交替运行所有的工作,从而优化响应时间,但二者不可得兼,这是系统问题,同时结合了I/O,但仍未解决操作系统看不到未来的问题(任务耗时)

被折叠的 条评论
为什么被折叠?



