考虑因素算法
为了构建调度策略,须要作一些简化假设,这些假设和系统中运行的进程相关,统称为工做负载(workload)缓存
(1)每个进程(工做)运行相同的时间性能
(2)全部工做同时到达,有时候当多个工做到达的时间相差很小的时候,也近似认为是同时到达的优化
(3)一旦开始工做,每一个工做将保持运行直到完成操作系统
(4)全部工做只是使用CPU,即:它们不执行I/O操做3d
(5)每一个工做的运行时间是已知的code
为了可以衡量不一样调度策略的优缺点,提出一个指标——周转时间(turnaround time)orm
(1)定义:任务完成时间减去任务到达的时间,即:blog
(2)当知足假设同时到达时,到达时间为0,周转时间等于完成时间 (3)周转时间是一个**性能**(performance)**指标**。而性能和公平在调度系统每每时矛盾的。调度系统能够优化性能,但代价时阻止一些任务运行,这就下降了公平
先进先出(FIFO)队列
先进先出(First In First Out):先就绪的工做先执行
假设有A、B、C三个工做,A比B早一点点,B比C早一点点,此时根据咱们的假设,能够将A、B、C近似看做时同时到达的。可是根据实际状况,是A先执行,其次是B,最后是C。假设每一个工做运行10s,求工做的平均周转时间(average turnaround time)?
A的周转时间为10s,B的周转时间为20s,C的周转时间为30s
平均周转时间为(10+20+30)/3=20
如今放宽假设1,让A、B、C运行时间不一样,考虑FIFO是否存在平均周转时间较长的状况
假设A、B、C三个工做,A运行时间为100s,B和C运行时间为10s,若是依旧是A先早到一点,而后是B,最后是C(仍然近似认为是同时到达的),此时系统的平均周转时间较长(100+110+120)/3=110
FIFO出现4这种状况被称为护航效应(convoy effect),即:一些耗时较少的潜在资源消耗者排在重量级的资源消费者后面。例如:在杂货店只有一个排队队伍的时候,你看见前面的装满了3辆购物车的货物时,这会让你等很长时间
最短任务优先(SJF)
最短任务优先(Shortest Job First):先运行最短的时间,而后是次短的时间,如此继续
依旧在上述4的状况下,按照SJF的策略,平均周转时间为(10+20+120)/3=50,和FIFO相比,显著下降了平均周转时间。但前提是知足假设2——同时到达
如今放宽假设2,即:工做可以随时到达,考虑SJF平均周转时间较长的状况
依旧是FIFO中4的状况,假设A在t=0时到达,而且须要运行100s,而B和C在t=10s到达,各自运行10s。则A的周转时间为100s,B的周转时间为110-10=100,C的周转时间为120-10=110。平均周转时间为(100+100+110)/3=103.33s
很明显当工做可以随时到达的状况下,SJF可能会出现平均周转时间较长的状况
最短完成时间优先(STCF)
最短完成时间优先(Shortest Time-to-Completion First):放宽假设3,即:调度程序能够安排其它工做抢占正在运行的工做占用的CPU。
在SJF中添加了抢占,每当新工做进入就绪状态时,它就会肯定剩余工做和新工做中,谁的完成时间最少,而后调度这个工做
在上述4的状况下,STCF将抢占A并先运行完B和C后,才会继续运行。则A的周转时间为120s,B的周转时间为10s,C的周转时间为20s,平均周转时间为(120+10+20)/3=50,显著下降了SJF相同状况下的平均周转时间
增长考虑因素
当符合假设四、5成立时,即:知道任务长度,而且任务只使用CPU,根据当前的惟一衡量指标为周转时间时,STCF是一个很好的策略。可是,引入分时系统时,就出现了问题,由于此时须要任务和用户进行交互,而周转时间没法衡量任务的交互性
响应时间(response time):可以衡量任务的交互性,定义为从任务到达系统到首次运行的时间
轮转(RR)
轮转(Round-Robin):在一个时间片内运行一个工做,而后切换到运行队列的下一个任务,而不是运行一个任务直到结束。它反复执行,直到全部任务完成。
时间片长度必须时时钟周期的倍数。若是不是,进行上下文切换的时候须要等待一段时间,此时CPU没工做,就浪费了CPU资源
假设3个任务,A、B、C在系统中同时到达,而且它们都但愿运行5s,SJF调度程序必须运行完当前任务才能运行下一个任务,而1s时间片的RR可以快速循环工做。RR平均响应时间为:(0+1+2)/3=1(注:同时到达,到达时间为0),SJF算法平均响应时间为(0+5+10)/3=5
时间片长度对RR相当重要,越短,RR在响应时间上的表现越好,可是时间片不能设置得过短:忽然上下文切换会影响总体性能。由于上下文切换的成本不只仅来自保存和恢复少许寄存器的操做系统操做。程序在运行时,还会在CPU高速缓存、TLB、分支预测器和其余片上的硬件中创建了大量的状态。因此时间片长度须要慎重权衡,让它足够长,以便摊销上下文切换成本,而又不会让系统不及时响应
摊销(amortize):经过减小成本的频度(即:执行较少的操做),系统的总成本就会下降。例如:若是时间片设置为10ms,而且上下文切换时间为1ms,大约会浪费10%的时间用于上下文切换。为了摊销这个成本,能够把时间片长度增长到100ms,则只有不到1%的时间会用于上下文切换。
在3中,咱们只考虑了响应时间,没考虑周转时间,若是计算RR的周转时间,A为13,B为14,C为15,平均14。而SJF的周转时间为,A为5,B为10,C为15,平均10.此时RR虽然响应时间较好,可是周转时间较差。
到目前为止。有两类调度程序
(1)SJF、STCF优化了周转时间,可是响应时间——交互性很差
(2)RR优化了响应时间,可是周转时间很差
结合I/O
放宽假设4,即:工做会执行I/O,此时调度程序会面临两个问题
(1)发起I/O请求作出决定,由于当前运行的任务在I/O期间不会使用CPU,它会被阻塞等待I/O完成。这时调度程序须要考虑是否等待该任务的执行仍是安排另外一项任务
(2)I/O完成时作出决定。I/O完成时会产生中断,操做系统运行并将发出I/O的进程从阻塞状态移回到就绪状态。此时调度程序将考虑是继续执行该任务,仍是执行其余任务
假设有两项工做A、B,每项工做须要50ms的CPU时间。A每运行10ms,就会发出一次I/O请求,而B只是单纯地使用CPU50ms.调度程序先运行A再运行B。假设构建STCF调度程序。能够将A的每一个10ms的子工做看做是一项独立的工做。因此任务运行时,先执行A10ms的子任务,完成后,会执行B,当I/O请求完成后,就会抢占B并运行10ms,这样就会充分利用系统。
多级反馈队列(MLFQ)
多级反馈队列(Multi-level Feedback Queue,MLFQ)须要解决的问题
(1)优化周转时间
(2)放宽假设5,即:不知道任务运行时间
(3)下降响应时间,获取更好的交互体验
基本构成:有许多独立的队列,每一个队列有不一样的优先级(priority level)
基本规则:
(1)规则1:若是A的优先级>B的优先级,运行A(不运行B)
(2)规则2:若是A的优先级=B的优先级,轮转运行A和B
如何改变优先级(1)?
(1)系统须要执行的任务能够分为下列两类
a. 运行时间很短、频繁放弃CPU的交互性任务
b. 须要不少CPU时间、响应时间不是很重要的长时间计算密集型任务
(2)优先级调整算法
a. 规则3:任务进入系统时,放在最高优先级(最上层队列)
b. 规则4a:任务用完整个时间片后,下降优先级(移入下一个队列)
c. 规则4b:若是工做再其时间片内主动释放CPU,则优先级不变
(3)实例1:单个长工做
下图展现了一个有三个队列的调度程序。该工做首先进入最高优先级(Q2),执行10ms的时间片后,优先级-1,最终进入Q1,并一直到执行完毕
(4)实例2:来了一个短工做
有两个工做:A时一个长时间运行的CPU密集任务,B是一个运行时间很短的交互型任务。假设A执行一段时间后B到达。下图中A(用黑色表示)在最低优先队列中(由(3)可知:长时间任务很长时间都会在最低队列中),B(用灰色表示)在时间T=100时到达,并加入最高优先级队列中。因为它运行时间很短,通过两个时间片,在被移入最低优先级队列以前,B执行完毕。而后A继续运行。
(5)MLFQ算法的目标:若是不知道任务时短任务仍是长任务,那么就在考试的时候假设它时短任务,并赋予最高优先级。若是确实是短任务,则会很快执行完毕。不然就会被慢慢移入低优先级队列,而这个时候该任务也被认为是长任务了。经过这种方式,MLFQ近似于SJF。
(6)实例3:有I/O
根据4b,交互型工做中有大量的I/O操做(好比等待用户的键盘或鼠标输入),它会在时间片用完以前放弃CPU,在这种状况下,咱们会保持它的优先级不变
假设交互型工做B(用灰色表示)每执行1ms便须要进行I/O操做,它与长时间运行的工做A(用黑色表示)竞争CPU。MLFQ算法保持B在最高优先级,由于B老是让CPU。若是B是交互型工做,MLFQ就进一步实现了它的目标,让交互型工做快速运行。
如今,MLFQ在长时间任务之间能够公平地分享CPU,又能给短工做或交互型工做很好地响应时间。这样就完美呢?其实还有问题
a. 饥饿问题(starvation)问题。即:系统有许多交互型工做,就会不停地抢占长时间任务地CPU,让它们永远没法获得CPU
b. 愚弄调度程序(game the scheduler)。即:进程在时间片用完以前,调用一个I/O操做(好比访问一个无关的文件),从而主动释放CPU。如此即可以保持吃在高优先级,占用更多的CPU时间
c. 一个程序可能在不一样时间表现不一样。即:一个计算密集型的进程可能在某段时间表现为一个交互型的进程
如何提升优先级(2)?
如何解决上述5中的问题?
周期性地提高全部任务地优先级。最简单的就是周期性的将全部任务放到最高优先级队列中
规则5:通过一段时间S,就将系统的任务从新加入到最高优先级队列中。
新规则解决的问题
(1)进程不会饿死——在最高优先级队列中,它会以RR的方式,和其余高优先级工做分享CPU,从而最终得到执行
(2)若是一个CPU密集型工做变成了交互型,当它的优先级提高,调度程序会正确对待它
下边有两张图,左边没有优先级提高,长时间任务在两个短任务到达后被饿死。右边的每隔50ms就有一次优先级提高(50ms只是举例),所以至少保证了长任务的工做会有必定的进程,每过50ms就被提高到最高优先级,从而按期得到执行。
剩余问题
(1)S的值如何设置?若是S设置得过高,长任务会被饿死,若是过低,交互型工做得不到合适的CPU时间比例
(2)如何阻止调度程序被愚弄?工做在时间片之内释放CPU就保留它的优先级是存在问题的
选择好的计时方式
更完善的CPU计时方式:调度程序应该记录一个进程在某一层消耗的总时间,只要进程用完了本身的配额,就将它降到低一级的优先级队列中。
重写规则4a和4b
规则4:一旦工做用完了其在某一层的时间配额(不管中间主动放弃了多少次的CPU),就下降其优先级(移入低一级队列)
下图对比了在规则4a、4b的策略下(左图),以及在新的规则4(右图)的策略下,一样试图愚弄调度程序的进程的表现。灭有规则4的保护下,进程能够在每一个时间片结束前发起一次I/O操做,从而垄断CPU时间,有了这样的保护,不管进程的I/O行为如何,都会慢慢下降优先级
MLFQ调优以及其余问题
问题:
(1)配置多少队列
(2)每一层队列的时间片配置多大
这些问题没有显而易见的答案,只有利用对工做负载的经验以及后续对调优程序的调优,才会取得使人满意的平衡
例如:高优先级队列一般只有较短的时间片,使得交互型工做可以更快的切换。而低优先级队列中更多的是CPU密集性工做,配置更长的时间片会更好
MLFQ规则小结
(1)规则1:若是A的优先级>B的优先级,运行A(不运行B)
(2)规则2:若是A的优先级=B的优先级,轮转运行A和B
(3) 规则3:任务进入系统时,放在最高优先级(最上层队列)
(4)规则4:一旦工做用完了其在某一层的时间配额(不管中间主动放弃了多少次的CPU),就下降其优先级(移入低一级队列)
(5)规则5:通过一段时间S,就将系统的任务从新加入到最高优先级队列中。