【操作系统】CPU调度和死锁

  高级调度又称为作业调度或长程调度,其主要功能是根据作业控制块中的信息,审查系统能否满足用户作业的资源需求,以及按照一定的算法,从外存的后备队列中选取某些作业调入内存,并为它们创建进程、分配必要的资源。然后再将新创建的进程插入就绪队列,准备执行。它的调度对象是作业。作业是一个比程序更为广泛的概念,它不仅包含了通常的程序和数据,而且还应配有一份作业说明书,系统根据该说明书来对程序的运行进行控制。在批处理系统中,是以作业为基本单位从外存调入内存的。为了管理和调度作业,在多道批处理系统中为每个作业设置了一个作业控制块JCB,它是作业在系统中存在的标志,其中保存了系统对作业进行管理和调度所需的全部信息

  低级调度称为进程调度或短程调度,它所调度的对象是进程(或内核进程)。低级调度用于决定就绪队列中的哪个进程应获得处理机,然后再由分派程序执行把处理机分配给该进程的具体操作。低级调度的主要功能有保存处理机的现场信息、按某种算法选取进程、把处理器分配给进程。有两种进程调度的方式:非抢占式调度和抢占式调度。

  在采用非抢占调度方式时,可能引起进程调度的因素可归结为1、正在执行的进程执行完毕,或因发生某事件而不能再继续执行;2、执行中的进程因提出I/O请求而暂停执行;3、在进程通信或同步过程中执行了某种原语操作,如P操作(wait操作)、Block原语、Wakeup原语等。非抢占式调度优点实现简单,开销小。缺点无法满足紧急任务。

  抢占方式的优点是,可以防止一个长进程长时间占用处理机,能为大多数进程提供更公平的服务,特别是能满足对响应时间有着较严格要求的实时任务的需求。但抢占方式比非抢占方式调度所需付出的开销较大。抢占式调度基于的原则:优先权原则、短作业有限原则、时间片原则。

  中级调度又称中程调度。引入中级调度的主要目的是为了提高内存利用率和系统吞吐量。为此,应使那些暂时不能运行的进程不再占用宝贵的内存资源,而将它们调至外存上去等待,把此时的进程状态称为就绪驻外存状态或挂起状态。中级调度实际上就是存储器管理中的对换功能

 

 

   选择调度方式和算法的准则有面向用户的和面向系统的。

  面向用户的准则:

  • 周转时间最短。是指从作业被提交给系统开始,到作业完成为止的这段时间间隔(称为作业周转时间)。它包括四部分时间:作业在外存后备队列上等待(作业)调度的时间,进程在就绪队列上等待进程调度的时间,进程在CPU 上执行的时间,以及进程等待I/O 操作完成的时间。系统则希望平均周转时间最短,可使得大多数用户满意。
  • 响应时间快。是从用户通过键盘提交一个请求开始,直至系统首次产生响应为止的时间。
  • 截止时间的保证。
  • 优先权准则。

  面向系统的准则:

  • 系统吞吐量高。
  • 处理机利用率好。
  • 各类资源的平衡利用。

调度算法

  在OS中调度的实质是一种资源分配,因而调度算法是指:根据系统的资源分配策略所规定的资源分配算法。

  先来先服务(FCFS)调度算法

  FCFS 算法比较有利于长作业(进程),而不利于短作业(进程)。

  短作业(进程)优先调度算法

  该算法对长作业不利,未考虑作业的紧迫程度。

  高优先权优先调度算法

  为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。分为非抢占式和抢占式。

  优先权的类型分为静态优先权和动态优先权。静态优先权是在创建进程时确定的,且在进程的整个运行期间保持不变。静态优先权根据进程类型、进程对资源的需求和用户要求确定。静态优先权法简单易行,系统开销小,但不够精确。动态优先权是指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。

  由上式可以看出:

  • (1) 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。
  • (2) 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。
  • (3) 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,其优先级便可升到很高,从而也可获得处理机。

  时间片轮转法

  在时间片轮转算法中,时间片的大小对系统性能有很大的影响,如选择很小的时间片将有利于短作业,因为它能较快地完成,但会频繁地发生中断、进程上下文的切换,从而增加系统的开销;反之,如选择太长的时间片,使得每个进程都能在一个时间片内完成,时间片轮转算法便退化为FCFS算法,无法满足交互式用户的需求。

  多级反馈队列调度算法

  多级反馈队列算法可以很好的处理交互作用,短作业和长作业。

  设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。

  当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列中便采取按时间片轮转的方式运行。

   仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。

  

实时调度

  实时调度需要的信息:就绪时间、开始截止时间和完成截止时间、处理时间、资源要求、优先级。

  假定系统中有m 个周期性的硬实时任务,它们的处理时间可表示为Ci,周期时间表示为Pi,则在单处理机情况下,必须满足下面的限制条件:

  假定系统中的处理机数为N,则应将上述的限制条件改为:

  

   实时调度通常采用采用抢占式调度机制,具有快速切换机制(对外部中断的快速响应能力、快速的任务分派能力)。

  实时调度算法的分类如下:

  

  常见的实时调度算法有:最早截止时间优先即EDF(Earliest Deadline First)算法、最低松弛度优先即LLF(Least Laxity First)算法。松弛程度就是任务紧急程度。 

死锁 

   死锁(Deadlock)是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

  产生死锁的原因:

  • 竞争资源:竞争非剥夺资源、临时性资源都可能导致死锁。资源分为可剥夺资源(指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺,CPU和主存均属于可剥夺性资源。)和非可剥夺资源(当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。)。资源也可分为永久性资源(可以重复使用的资源)和临时资源(指由一个进程产生,被另一进程使用一短暂时间后便无用的资源)。
  • 进程间推进顺序非法

  产生死锁的必要条件:

  • 互斥条件:进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。
  • 请求和保持条件:进程已经保持了至少一个资源,又提出了新的资源请求,但是该资源已经被其他进程占有,此时请求进程阻塞。
  • 不剥夺条件:进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
  • 环路等待条件:指在发生死锁时,必然存在一个进程—资源的环形链。

  处理死锁的方法:

  • 预防死锁。
  • 避免死锁。
  • 检测死锁。
  • 解除死锁。

  预防死锁

  该方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来预防发生死锁。由于所施加的限制条件往往太严格,因而可能会导致系统资源利用率和系统吞吐量降低。预防死锁的方法是使四个必要条件中的第2、3、4 个条件之一不能成立,来避免发生死锁。至于必要条件1互斥条件,因为它是由设备的固有特性所决定的,不仅不能改变,还应加以保证。

  破坏请求和保持条件:系统规定所有进程在开始运行之前,都必须一次性地申请其在整个运行过程所需的全部资源。其优点是简单、易于实现且很安全。缺点为资源被严重浪费和使进程延迟运行。在允许的情况(较为简单的情况)下也可以一个一个申请,即申请一个用完就释放

  破坏不剥夺条件:当一个已经保持了某些资源的进程,再提出新的资源请求而不能立即得到满足时,必须释放它已经保持了的所有资源,待以后需要时再重新申请。这延长了进程的周转时间,增加了系统开销,降低了系统吞吐量。

  破坏环路等待条件:这种方法中规定,系统将所有资源按类型进行线性排队,并赋予不同的序号。所有进程对资源的请求必须严格按照资源序号递增的次序提出,这样,在所形成的资源分配图中,不可能再出现环路。这限制了新类型设备的增加,造成资源浪费,按规定次序申请的方法,必然会限制用户简单、自主地编程。

  避免死锁

  并不须事先采取各种限制措施去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。由于施加较弱的限制条件,便可获得较高的资源利用率及系统吞吐量,但在实现上有一定的难度。系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可避免发生死锁。允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,令进程等待。

  所谓安全状态,是指系统能按某种进程顺序(P1,P2,…,Pn)(称〈P1,P2,…,Pn〉序列为安全序列),来为每个进程Pi分配其所需资源,Pi执行结束后释放资源可供Pi+1使用,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。

  使用银行家算法可以避免死锁。

  算法数据结构:

  可用资源数组Available:  数组大小m表示有m类资源,数组元素表示系统中某类资源可用数目。
  最大需求矩阵Max:  n×m 的矩阵,定义了系统中n个进程中的每一个进程对m类资源的最大需求。
  分配矩阵Allocation:  n×m 的矩阵,定义了每一个进程当前已分配给每一类资源数。
  需求矩阵Need:  n×m的矩阵,用以表示每一个进程还需要的各类资源数。

  

  进程i的某一次请求资源数组Request_i:  大小为m,元素为本次要申请每类资源的数目。

  工作数组Work:  表示系统当前可提供的各类资源数目,它含有m个元素,在执行安全算法开始时,Work:=Available。

  数组Finish:  它表示系统是否有足够的资源分配给进程,使之运行完成,大小为n。开始时先做Finish[i]:=false;当有足够资源分配给进程时,再令Finish[i]:=true。

 

   算法步骤:

  1. 如果Request i[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
  2. 如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi 须等待。
  3. 系统试探着把资源分配给进程P i,并修改下面数据结构中的数值:

  4.系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

 

  安全性算法步骤:

  1. 设置两个向量:Work:=Available,Finish[i]:=false;
  2. 从进程集合中找到一个能满足下述条件的进程:
    ① Finish[i]=false;② Need[i,j]≤Work[j](系统的资源可以满足该进程);若找到,执行步骤3,否则,执行步骤4。

  3. 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:Work[j]:= Work[j]+Allocation[i,j](此时假设Pi已经执行完毕);Finish[i]:=true;go to step 2;
  4. 如果所有进程的Finish[i]=true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

 

  检测死锁

  并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,而是允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源; 然后,采取适当措施,从系统中将已发生的死锁清除掉。检测的前提是系统保存有关资源的请求和分配信息。

  死锁定理:S(资源分配图)状态为死锁状态的充分条件是:当且仅当S状态的资源分配图是不可完全简化的。

  资源分配图

  (1) 把N 分为两个互斥的子集,即一组进程结点P={p1,p2,…,pn}和一组资源结点 R={r1,r2,…,rn},N=P∪R。(2) 凡属于E中的一个边e∈E,都连接着P中的一个结点和R中的一个结点,e={pi,rj}是资源请求边,由进程pi指向资源rj,它表示进程pi请求一个单位的rj资源。e={rj,pi}是资源分配边,由资源rj指向进程pi,它表示把一个单位的资源rj分配给进程pi。

 

  资源分配图简化

  1. 在资源分配图中,找出一个既不阻塞又非独立的进程结点Pi。在顺利的情况下,Pi可获得所需资源而继续运行,直至运行完毕,再释放其所占有的全部资源,这相当于消去pi所求的请求边和分配边,使之成为孤立的结点。将图a中p1的两个分配边和一个请求边消去,便形成图(b)所示的情况。
  2. p1释放资源后,便可使p2获得资源而继续运行,直至p2完成后又释放出它所占有的全部资源,形成图(c)所示的情况。
  3. 在进行一系列的简化后,若能消去图中所有的边,使所有的进程结点都成为孤立结点,则称该图是可完全简化的;若不能通过任何过程使该图完全简化,则称该图是不可完全简化的。

 

  解除死锁

  与检测死锁相配套的一种措施。常采用解除死锁的两种方法是:

  • (1) 剥夺资源。从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。
  • (2) 撤消进程。最简单的撤消进程的方法是使全部死锁进程都夭折掉;稍微温和一点的方法是按照某种顺序逐个地撤消进程,直至有足够的资源可用,使死锁状态消除为止。

  在出现死锁时,可采用各种策略来撤消进程。例如,为解除死锁状态所需撤消的进程数目最小;或者,撤消进程所付出的代价最小等。

 

 

posted @ 2020-05-31 21:03  Chen沉尘  阅读(1323)  评论(0编辑  收藏  举报