第三章处理机调度与死锁.docx
《第三章处理机调度与死锁.docx》由会员分享,可在线阅读,更多相关《第三章处理机调度与死锁.docx(27页珍藏版)》请在冰豆网上搜索。
第三章处理机调度与死锁
第三章处理机调度与死锁
第一节处理机调度引论
作业、进程状态及其转换图
一、处理机的分级调度
1、从上图中可以看出:
(1)一个用户作业从建立到最后执行(正常或非正常)结束,中间可能要经历各种处理机调度。
(2)系统的调度是分层次的。
2、处理机调度的层次
一般来说,处理机调度可分为4级:
作业调度、交换调度、进程调度、线程调度。
(1)作业调度(高级调度)P6-9
在每次执行作业调度时,都须做出以下两个决定:
●接纳多少个作业
●接纳哪些作业
(2)进程调度(低级调度)
就是确定就绪队列中哪个进程应该获得处理机,然后再由分派程序执行把处理机分配给该进程的具体操作(进程切换)。
功能:
P12
进程调度中有三种基本机制:
P13-15
进程调度进一步分为抢占式和非抢占式两种调度方式。
●非抢占方式(Non-preemptiveMode)
一旦将处理机分配给某进程,便让该进程一直执行,直到该进程完成或因某事件而阻塞,主动放弃处理机时,OS才再将处理机分配给其他进程。
不允许某进程抢占已经分配出去的处理机。
在采用非抢占调度方式时,可能引起进程调度的因素可归结为这样几个:
①正在执行的进程执行完毕,或因发生某事件而不能再继续执行;
②执行中的进程因提出I/O请求而暂停执行;
③在进程通信或同步过程中执行了某种原语操作,如P操作(wait操作)、Block原语、Wakeup原语等。
这种调度方式的优点是实现简单、系统开销小,适用于大多数的批处理系统环境。
但它难以满足紧急任务的要求----立即执行,因而可能造成难以预料的后果。
显然,在有比较严格的实时要求的系统(包括分时系统)中,不宜采用这种调度方式。
●抢占方式(PreemptiveMode)
允许OS的调度程序根据某种原则,暂停某个正在正常执行的进程,将已经分配给该进程的处理机收回,重新分配给另一个进程。
抢占原则有(P19):
①优先权原则
②短作业(进程)优先原则
③时间片原则
(3)交换调度(中级调度)
为了提高内存利用率和系统吞吐量,应使那些暂时没机会运行的进程不再占用宝贵的内存资源,而将它们调至外存上去等待,把此时的进程状态称为就绪驻外存状态或挂起状态;当挂起进程重又具备运行条件、且内存又稍有空闲时,由中级调度来决定把外存上的那些又具备运行条件的就绪进程,重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待进程调度。
交换调度主要涉及内存管理和扩充,一般将它归于存储管理中;
只有在多道批处理系统中才有作业调度,而在分时和实时系统中一般只有进程调度、交换调度和线程调度;
其中,进程调度是最基本的调度,是OS处理机调度中主要讨论的内容。
二、调度队列模型
1、仅有进程调度的调度队列模型
在实时、分时系统中,通常只有进程调度。
用户的启动命令和数据被直接送入内存,OS立即为其建立进程,插入就绪队列。
通常把就绪进程组织成FCFS(FIFO)队列的形式,新进程插到队尾。
每个进程在执行时都可能出现以下三种情况:
(1)任务在给定的时间片内已经完成,该进程便在释放处理机后进入完成状态;
(2)任务在本次分得的时间片内尚未完成,OS便将该任务再放入就绪队列的末尾;
(3)在执行期间,进程因为某事件而被阻塞后,被OS放入阻塞队列。
图3-1仅具有进程调度的调度队列模型
2、具有高级和低级调度的调度队列模型
图3-2具有高、低两级调度的调度队列模型
在多道批处理系统中,不仅有进程调度,还有作业调度。
作业在外存上组成后备队列,作业调度按一定的算法从后备队列中选择一批作业送入内存,为它们创建进程,并将新创建的进程插入就绪队列。
进程调度则按一定的算法为就绪的进程分配处理机。
该模型与上一模型的主要区别在于如下几个方面:
具有后备队列;
就绪队列的组织形式(一般采用高优先权优先,同优先权的进程FCFS。
)
可以设置多个阻塞队列。
3、同时具有三级调度的调度队列模型
当OS引入了交换调度后,就绪队列和阻塞队列都分别有了内存和外存两种队列(静止就绪队列、活动就绪队列,静止阻塞队列、活动阻塞队列)
图3-3具有三级调度时的调度队列模型
三、选择/设计调度方式和调度算法的原则
以下列举的是设计OS处理机调度的一系列原则,有的是面向用户的,有的是面向系统的。
在设计OS时,选择什么样的调度方式和调度算法,取决于系统的设计目标和OS的类型。
通常要在面向系统和面向用户的各原则之间选择并取得平衡。
1、面向用户的原则
(1)周转时间短原则P31
●周转时间T:
作业完成时间–作业进入系统时间
可把n个作业(一批作业)的平均周转时间描述为:
●带权周转时间:
作业的周转时间T与系统为它提供服务的时间TS(单道环境作业需要的运行时间)之比,即:
W=T/TS。
而n个作业的平均带权周转时间则可表示为:
平均带权周转时间能更公平地描述系统的性能。
(2)响应时间快原则P34
(3)截止时间有保证原则P35
(4)优先权准则P35
2、面向系统的原则P36-38
(1)系统高吞吐量原则(与周转时间短原则一致)
(2)处理机高利用率原则
(3)各类资源平衡利用原则
第2节调度算法
一、先来先服务算法(FCFS/FIFO)
它是一种简单的、基础的算法,优先考虑在系统中等待时间最长的进程(作业)。
它既可以用在进程调度,也可以用在作业调度。
算法描述:
OS的调度程序每次从就绪(后备)队列中选取一个(一组)最先进入队列的进程(作业),为之分配处理机使之投入运行(将其读入内存,建立进程,插入就绪队列)。
该进程一直运行直到完成或因某事件而进入阻塞。
例如:
它比较有利于长作业,而不利于短作业。
这种算法常和其他算法结合使用。
二、短进程(作业)优先调度算法
算法描述:
OS的调度程序每次从就绪(后备)队列中选取一个(一组)估计运行时间最短的进程(作业),为之分配处理机使之投入运行(将其读入内存,建立进程)。
该进程一直运行直到完成或因某事件而进入阻塞。
它是一种有利于短作业或进程的调度算法。
它能有效地提高系统的吞吐量和平均带权周转时间。
但是,它也存在不容忽视的缺点:
(1)会增加长作业的带权周转时间,更严重的是,如果有一长进程(作业)进入系统的就绪队列(后备队列),由于调度程序总是优先调度那些(即使是后进来的)短进程(作业),将导致长进程(作业)长期不被调度。
(2)该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理。
(3)由于作业(进程)的长短只是根据用户所提供的估计执行时间而定的,而用户又可能会有意或无意地缩短其作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。
三、优先权调度算法
1、非抢占式优先权算法
算法描述:
系统把处理机分配给就绪队列中优先权最高的进程,该进程将一直执行下去,直至完成、或因发生某事件使该进程放弃处理机,系统方可再将处理机重新分配给另一优先权最高的进程。
这种调度算法主要用于批处理系统中;也可用于某些对实时性要求不严的实时系统中。
2、抢占式优先权算法
算法描述:
系统把处理机分配给优先权最高的进程,使之执行。
在其执行期间,只要又有另一个优先权更高的进程到达就绪队列,调度程序就立即停止当前进程(原优先权最高的进程)的执行,将其送回就绪队列,然后将处理机分配给新到达的优先权最高的进程。
在采用这种调度算法时,每当系统中有新进程i到达就绪队列时,就将其优先权Pi与正在执行的进程j的优先权Pj进行比较。
如果Pi≤Pj,原进程j便继续执行,新到进程i插入就绪队列;但如果是Pi>Pj,则立即停止j进程的执行,做进程切换,使i进程投入执行。
显然,这种抢占式的优先权调度算法,能很好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中。
3、优先权的确定
(1)静态优先权
静态优先权是在创建进程时确定的,且在进程的整个运行期间保持不变。
一般地,优先权是利用某一范围内的一个整数来表示的,例如,0~7或0~255中的某一整数,又把该整数称为优先数。
一般数字越大优先权越高,也可以反过来。
确定进程优先权的依据有如下三个方面:
P51
●进程类型。
●进程对资源的需求。
●用户要求(应用的需求)。
(2)动态优先权
优先权可以是静态的,也可以是动态的。
动态优先权是指,在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而变化的,以便获得更好的调度性能。
每次调度前计算就绪队列中所有进程的优先权,将优先权最高的作业投入运行。
(3)动态优先级调度策略举例----高响应比优先调度算法
优先权的变化规律可描述为响应比:
=1+等待时间/要求服务时间
●如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。
●当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。
●对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,优先级便可升到很高,从而也可获得处理机。
动态优先权调度算法,结合抢占式调度方式,可获得较好的调度性能。
四、基于时间片的轮转调度算法
基本思想:
把CPU的时间划分成若干时间片,并且按顺序赋给就绪队列中的每一个进程,使进程轮流占有CPU。
当一个进程的本轮时间片用完时,即使进程未执行完毕,系统也剥夺该进程的CPU,将该进程排在就绪队列末尾。
同时系统选择另一个进程运行。
1、简单轮转法
算法描述:
系统将所有就绪进程按FIFO规则排队;将处理机时间分成等长的时间片,将时间片轮流分配给就绪队列中的进程。
这样,在一段时间内,就绪队列中所有进程均有机会获得一个时间片的处理机时间而运行。
在轮转法中,时间片长度的选取非常重要,它会直接影响系统开销和响应时间。
P58
与时间片大小有关的因素:
●系统响应时间要求
●就绪进程个数
●CPU能力
2、多级反馈轮转法
算法描述:
在内存中设置多个就绪队列,每个就绪队列按FIFO的方式组织;每个就绪队列被赋予不同的优先级和不同长度的时间片,优先级最高的第一级队列,时间片最小。
随着优先级的降低,队列的时间片逐步加大;
图3-5 多级反馈队列调度算法
调度:
●一个新创建的就绪进程,进入第一级队列;
●调度从第一级队列开始。
当第一级队列空时,就去调度第二级队列,如此类推;(调度总是发生在目前优先级最高的非空队列上)
●当时间片到后,没有执行完的进程被剥夺CPU,插入下一级就绪队列末尾;
●等待队列中的阻塞进程,一旦等待的事件发生,则回到原来的就绪队列末尾;
●当有一个优先级更高的进程就绪时,可以抢占CPU,被抢占的进程回到原来的就绪队列末尾。
算法的性能分析:
这是时间片轮转和静态优先权调度相结合的算法。
●所有类型的作业用户都会在很短的时间内启动,并会有所响应;
●终端型用户作业、短批处理作业用户,能在较短的时间内完成;
●系统吞吐率高;
●长批处理作业,能够最终得到处理。
第3节实时调度
一、实时调度的特点
1、实时系统:
要求计算机在用户任务允许的时限范围内给出响应信号。
2、实时事件的分类:
可分为硬实时任务和软实时任务。
其中,前者要求计算机系统必须在给定的截止时限内完成(开始)任务,后者允许计算机系统在给定的时限左右处理完毕,可以有一定的延时。
二、实现实时调度的基本条件
1、提供必要的信息(就绪时间、开始截止时间/完成截止时间、处理时间、资源要求、优先级)
2、系统处理能力强(系统可能调度)P69
3、一般采用抢占式调度机制
4、具有快速切换机制P72
三、实时调度算法的分类
1、非抢占式调度算法:
●非抢占式轮转调度算法
●非抢占式优先权调度算法
2、抢占式调度算法:
●基于时钟中断的抢占式优先权调度算法P75
●立即抢占优先权调度算法P76
四、常用实时调度算法(一般都是优先权调度算法,只是确定优先权的策略不同)
1、最早(开始)截止时间优先(EDF)算法P78
图3-7EDF算法用于非抢占调度方式
2、最低松弛度优先(LLF)算法
进程“松弛度”的定义:
松弛度=完成截止时刻–当前时刻–还需要的运行时间
松弛度反映了任务的紧迫程度。
此算法是根据任务紧急(或松弛)的程度,来确定任务的优先级。
它主要用于抢占调度方式中。
每当CPU空出、有新就绪进程进入或到达时间单位时计算各进程的松弛度。
图3-7A和B任务每次的完成截止时间
例如:
如图3-7,在一个实时系统中,有两个周期性实时任务A和B,任务A要求每20ms执行一次,执行时间为10ms;任务B只要求每50ms执行一次,执行时间为25ms。
在刚开始时(t1=0),A1必须在20ms时完成,而它本身运行又需10ms,可算出A1的松弛度为10ms;B1必须在50ms时完成,而它本身运行就需25ms,可算出B1的松弛度为25ms,故调度程序应先调度A1执行。
在t2=10ms时,A2的松弛度可按下式算出:
A2的松弛度=完成截止时间-本身的运行时间-当前时间
=40ms-10ms-10ms=20ms
类似地,可算出B1的松弛度为15ms,调度程序应选择B1运行。
t3=30ms时,A2的松弛度已减为0,B1的松弛度为15ms,于是调度程序应抢占B1的处理机而调度A2运行…….
图3-8利用ELLF算法进行调度的情况
根据系统的情况,每隔10ms,或CPU空闲时,系统计算一次所有就绪、执行状态进程的松弛度,再采用抢占式调度。
从以上讨论可以看出,抢占式动态优先级调度算法可以较好地满足实时系统的要求,但计算进程的优先级,会占用较大的系统开销,因此要求系统有较强的能力。
五、关于优先级倒置及其解决方案
1、优先级倒置的形成:
P102-103,图3-10
2、优先级倒置的解决方案:
P102,图3-11
第4节死锁产生的原因和必要条件
一、死锁的定义
1、死锁的引例:
●设系统有一台打印机(R1)一台扫描仪(R2),两进程共享这两台设备。
●用信号量S1表示R1是否可用,用信号量S2表示R2是否可用,S1、S2初值为1。
这两个进程在并发执行过程中,可能会发生死锁。
(Why?
)能避免死锁的发生吗?
(How?
)
2、死锁的定义
指多个进程由于竞争资源而造成的一种僵局,若无外力作用,这些进程都将永远不能再向前推进。
即:
一组并发进程中,每个进程都在无限等待被该组中另一进程所占有的资源,因而都永远无法得到所需资源、向前推进,这种现象称为进程死锁,这一组进程就被称为死锁进程。
陷入死锁状态的进程称为死锁进程,而需要死锁进程已占用的资源或者需要与它们进行某种合作的其它进程就会相继陷入死锁,大量系统资源浪费,最终可能导致整个系统处于瘫痪状态。
3、资源的分类
●根据使用性质:
可剥夺资源和非剥夺性资源。
P92
●根据使用方式:
共享资源和独占资源。
●根据使用期限:
永久(可再用)资源和临时性(可消耗性)资源。
二、产生死锁的原因
1、资源竞争
系统提供的某类资源个数少于并发进程所需要的该类资源的总数,引起它们对资源的竞争而产生死锁,这是死锁产生的根本原因。
(1)竞争非剥夺性资源造成死锁P94图3-13
(2)竞争临时性资源P95-96,P97图3-14
2、进程间推进顺序不当
进程在运行过程中,请求和释放资源的顺序不当,导致进程死锁。
图3-14进程推进顺序对死锁的影响
三、产生死锁的必要条件P101-102
1、互斥条件
2、不剥夺条件
3、部分分配(请求和保持)条件
4、环路等待条件
当以上4个条件中有一个不满足,死锁就可以解除。
四、处理死锁的基本方法P103-106
1、预防死锁
2、避免死锁
3、检测死锁
4、解除死锁
第5节死锁的预防与避免
一、预防死锁
在系统设计时确定资源分配算法,设定限制,破坏产生死锁的四个必要条件之一。
P107-113
●资源一次性分配;(第一种协议)
●第二种协议;P109
以上两种方法,旨在破坏请求和保持条件。
●资源可剥夺;即当某进程新申请的资源得不到满足时释放已占有的资源(破坏不可剥夺条件)
●资源有序分配;系统给每类资源赋予一个编号,每一个进程按编号递增的顺序申请得到资源(破坏环路等待条件)
二、避免死锁
1、避免死锁的定义(方法的总体思想)
在系统运行过程中,OS对进程发出的每一次系统目前能够满足的资源申请进行动态检查,判断资源分配后系统是否可能发生死锁,从而决定是否进行资源分配。
若分配后系统可能发生死锁,则不予分配,否则就给予分配。
2、安全状态与不安全状态
安全状态是指,对于系统中的所有并发进程,系统能按某种进程推进顺序(存在一个进程推进序列)来为每个进程分配其所需资源,直至进程的最大需求,使每个进程都可顺序完成。
若系统当前不存在这样一个进程序列,则称系统处于不安全状态。
(1)安全序列----是一个进程推进运行的序列
一组有n个并发进程。
一个进程推进序列{P1,P2,P3,…,Pn}是安全的,即:
在这一时刻,对于序列中每一个进程Pi(1≤i≤n),它继续运行直到完成尚需要的资源量,不超过:
系统当前剩余资源量+排在它前面的所有进程当前占有资源量之和。
当系统中的所有并发进程目前存在一个进程推进的安全序列,系统就处于安全状态;否则,就处于不安全状态。
(2)安全序列和安全状态举例
假定系统中有三个并发进程A、B和C,共有12台磁带机。
进程A总共要求10台磁带机,B和C分别要求4台和9台。
假设在T0时刻,进程A、B和C已分别获得5台、2台和2台磁带机,尚有3台空闲。
(状态如下表所示)
显然,此时刻存在一个安全序列BAC。
3、由安全状态向不安全状态的转换
如果不按照安全序列分配资源、推进进程,系统就可能会由安全状态进入不安全状态。
例如,在T0时刻以后,C又请求1台磁带机,若此时系统把剩余3台中的1台分配给C,则系统便进入不安全状态。
因为,此时也无法再找到一个安全序列。
例如,把其余的2台分配给B,这样,B在完成后只能释放出4台,既不能满足A尚需5台的要求,也不能满足C尚需6台的要求,致使它们都无法推进到完成,彼此都在等待对方释放资源,即陷入僵局,结果导致死锁。
安全状态与不安全状态:
4、避免死锁的银行家算法
该算法综合考虑,给n个并发执行的进程分配m类临界资源,每类资源可能有若干个。
(1)算法中的数据结构
●可利用资源向量Available
这是一个含有m个元素的一维数组,其中的每一个数组元素代表系统中某一类资源当前的空闲数目。
其初始值是系统中所配置的该类全部可用资源的数目;其数值随该类资源的分配和回收而动态地改变。
如Available[j]=K,则表示系统中目前j类资源空闲K个。
●最大需求矩阵Max
矩阵的每一行是一个进程的最大需求向量,它的第j个元素代表这个进程运行完成需要j类资源的最大数量;如果Max[i,j]=K,则表示进程i需要j类资源的最大数目为K。
由系统中目前并发执行的n个进程的最大需求向量组成Max,这是一个n×m的矩阵。
它定义了系统中n个进程中的每一个进程对系统的m类资源的最大需求。
●已分配矩阵Allocation
矩阵的每一行是一个进程的已分配资源向量,它的第j个元素代表目前系统已经分配给该进程j类资源的数量;如果Allocation[i,j]=K,则表示进程i当前已获得j类资源的数目为K。
由系统中目前并发执行的n个进程的已分配资源向量组成Allocation,这也是一个n×m的矩阵。
它定义了系统中每一类资源当前已分配给每一进程的资源数。
●需求矩阵Need
矩阵的每一行是一个进程的还需要资源向量,它的第j个元素代表该进程继续运行至完成还需要j类资源的数量;如果Need[i,j]=K,则表示进程i还需要j类资源K个,方能完成其任务。
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。
上述三个矩阵存在如下关系:
Need[i,j]=Max[i,j]–Allocation[i,j]
以上四个数据结构描述了系统当前资源分配的一个状态。
●资源请求向量Requesti
进程i的一次资源请求用资源请求向量Requesti来描述。
如果Requesti[j]=K,表示这一次请求中,进程i申请j类型的资源K个。
(2)银行家算法
每当进程i发出一个资源请求后(对应地,有一个请求向量),系统按下述步骤进行检查:
步骤1:
检查请求的合理性:
如果Requesti[j]≤Need[i,j],则合理,转向步骤2;否则认为出错,因为它所申请的资源数已超过它所宣布的最大值;
步骤2:
检查请求的可行性:
如果Requesti[j]≤Available[j],便转向步骤3;否则,表示尚无足够资源,进程i须等待;
步骤3:
系统试探着把资源分配给进程i,修改下面数据结构中的数值:
Available[j]∶=Available[j]-Requesti[j];
Allocation[i,j]∶=Allocation[i,j]+Requesti[j];
Need[i,j]∶=Need[i,j]-Requesti[j];
步骤4:
调用安全性算法,检查此次资源分配后,系统是否仍处于安全状态。
若是,才正式将资源分配给进程i,以完成本次分配;否则,将本次的试探分配作废,撤消对数据结构的修改,恢复原来的资源分配状态(做步骤3计算的逆运算),让进程i等待。
(3)安全性算法----找一个安全序列:
步骤1:
设置两个向量,并给它们赋初值:
①工作向量Work,它表示系统目前可提供给进程继续运行使用的各类资源数目,它是一个含有m个元素的一维数组。
在开始执行安全算法时,赋初值Work:
=Available;
②完成向量Finish,它表示系统目前是否有足够的资源分配给系统中的n个进程,使之运行直到完成。
它含有n个元素。
当系统目前有足够资源分配给进程i时,令Finish[i]:
=true;算法开始时先给Finish赋初值Finish[i]:
=false;
步骤2:
从进程集合中找到一个同时能满足下述两条件的进程i:
①Finish[i]=false;
②进程i的每个Need[i,j]≤Work[j];
若能找到,执行步骤(3);否则,执行步骤(4);
步骤3:
由于当进程i获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故可以执行:
Finish[i]:
=true;/*将进程i放入推进序列*/
每个Work[j]:
=Work[j]+Allocation[i,j];/*回收进程i的全部资源*/
goto步骤2;
步骤4:
经过逐一计算,如果所有进程都满足:
Finish[i]=true,进入了进程推进序列,这个序列就是安全序列,这表示系统目前处于安全状态;否则,说明有若干个进程无法进入推进序列,系统处于不安全状态。
(4)银行家算法举例
●假定系统中有五个进程{P0,P1,P2,P3,P4}和三类资源{A,B,C},各资源的最大数量分别为10、5、7,在T