在多道程序环境下,内存中存在着多个进程,其数目往往多于处理机数目。这就要求系统能按照某种算法,动态地将处理机分配给处于就绪状态的一个进程,使之执行。因而,处理机调度是OS中至关重要的部分。
处理机调度实质上是对处理机资源进行分配。
三种调度相比较:进程调度的运行频率最高 、作业调度频率最低 、中级调度界于之间
FCFS调度算法
一种最简单的调度算法。既可用于作业调度,也可用于进程调度。
①作业调度:从后备队列作业中,选择一个或几个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入进程就绪队列。
②进程调度:从就绪队列中,选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后,才放弃处理机。——非抢占式
eg.
FCFS算法比较有利于长作业(进程),不利于短作业(进程)。经常与其他调度算法相结合
有利于CPU繁忙型作业(进程),不利于I/O繁忙型作业(进程)——因非抢占式
CPU繁忙型作业——需要大量的CPU时间进行计算,而很少请求I/O。如,科学计算
I/O繁忙型作业——是指CPU进行处理时,需频繁地请求I/O。如,大多数事务处理
SJF调度算法
①短作业优先(SJF)调度算法—— 从后备队列中选择一个或几个估计运行时间最短的作业,将它调入内存运行。
②短进程优先(SPF)调度算法——从就绪队列中选择一个估计运行时间最短的作业,将处理机分配给它,使它立即执行并一直到完成,或发生某事件而被阻塞放弃处理机时,再重新调度。(非抢占式)
eg.
从已进入的作业中选择运行时间最短的
优点:当多个作业同时到达时,SJF算法可使平均周转时间最短。
缺点:
该算法对长作业不利——长作业可能长期不被调度,甚至“饿死”。
未考虑作业的紧迫性,不能保证紧迫作业(进程)会被及时调度。
由于作业(进程)的长短只是根据用户所提供的估计时间而定的,致使该算法不一定能真正做到短作业优先调度。
人—机无法实现交互
该算法综合了FCFS(要求服务时间相同时,等待时间越长响应比越高)和SJF(等待时间相同时,要求服务时间越短,响应比越高)算法的优点:既考虑公平性,又考虑平均周转时间
缺点:增加系统开销——每次调度都要计算响应比。
eg.
用于进程调度。早期,分时系统采用的是简单的时间片轮转法; 90年代后,广泛采用多级反馈队列调度算法。
该方法采取了非常公平的处理机分配方法,即让就绪队列上的每个进程每次仅运行一个时间片。若就绪队列n个进程,每个进程每次获得1/n的处理机时间。
基本原理:
①系统把就绪队列中的所有进程,按先来先服务的原则,排成一个队列;
②每次调度时,把CPU分配给队首进程,并让它执行一个时间片;
③每当执行的时间片用完,调度程序便停止该进程的执行,将其送入就绪队列尾部;然后进行下一次进程调度。
进程切换两个原则:(1)若一个时间片未用完,正在运行的进程便已经完成,立即激活调度程序,开始下一个。(2)在一个时间片用完时,计时器中断处理程序被激活,若进程未运行完毕,调度进程把它送往就绪队列末尾。
时间片大小是略大于一次典型的交互所需要的时间。通常几ms~几百ms
②动态优先级: 在创建进程时所赋予的优先权,是可以随进程得推进,或随其等待时间的增加而改变的,以便获得更好的调度性。 eg.在采用抢占式优先权调度算法时,如果再规定当前执行进程以速率β下降,则可防止一个长作业长期垄断处理机.
该算法将系统中的就绪队列从一个拆分为若干个,将不同类型或性质的进程固定分配在不同的就绪队列,不同的就绪队列采用不同的调度算法,一个就绪队列中的进程可以设置不同的优先级,不同的就绪队列本身也可以设置不同的优先级。系统可以根据不同用户进程的需求,提供多种调度策略。
之前介绍的进程调度算法都有一定的局限性。而多级反馈队列调度算法不必事先知道各进程所需的执行时间,而且还可以满足各种类型进程的需要,是目前被公认的一种较好的进程调度算法 。
调度机制:
(1)设置多个就绪队列,每个队列赋予不同的优先级。第一队列优先级最高,其余逐个降低。该算法为每个队列富裕的执行时间片大小不同,优先级愈高,时间片愈小。
(2)每个队列采用FSFC算法。若轮到某进程执行时,能在时间片内完成,便可撤离系统,否则注入第二队列末位等待,第二队列仍未完成,调入第三队列…
(3)按队列优先级调度。调度程序首先调度最高优先级队列中的就绪进程运行。仅当1~(i-1)所有队列空闲时,才会调度第i队列中的进程运行。若处理机正在第 i 队列服务时有新进程进入任一优先级较高的队列,则必须把正在运行的进程放回到第 i 队列末尾,把处理机分配给高优先级进程。
eg.第一队列时间片为1,第i队列时间片为(2(i-1)),每运行一个时间片后,进程优先级降一级
死锁定义:如果一组进程中的每一个进程都在等待仅由该组进程中其他进程才能引发的事件,那么该组进程是死锁的。
系统中有许多不同类型资源,可以引起死锁的主要是,需要采用互斥访问方法的、不可以被抢占的资源,即临界资源。
竞争不可抢占性资源引起死锁
系统中所拥有的不可抢占性资源其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局(无限等待,形成死锁)。
进程推进顺序不当引起死锁:由于进程具有异步特征,这就使得进程可能按下列两种顺序向前推进:
①进程推进顺序合法:进程P1和P2并发执行时,若按曲线① 即:
P1:Request(S1);→P1:Request(S2);→P1:Release(S1);→Release(S2);→P2:Request(S1);→P2:Request(S2);→ P2:Release(S1);→Release(S2);则两个进程可顺利完成,不会产生“死锁”。类似地,曲线②和曲线③也不会产生“死锁”
②进程推进顺序非法:进程P1和P2并发执行时,若按曲线④ 即:P1:Request(S1);→P2:Request(S2);→ P1:Request(S2); 阻塞。→ P2:Request(S1); 阻塞。则两个进程间互相产生了阻塞,从而产生“死锁”
把区域D称为是“死锁区”
产生死锁的必要条件:产生死锁——》(1、2、3、4)
产生死锁必须同时具备下面四个必要条件。以下任一条件不成立,死锁就不会发生
(1)互斥条件:进程要求对所分配的资源进行互斥性访问。即在一段时间内某资源仅为一个进程所占有,如果此时还有其它进程要求访问该资源,则要求者只能被阻塞,直到该资源的占用进程用毕释放;
(2)请求和保持条件:当进程已经占有了至少一个资源,若又提出了新的资源请求,而该资源又被其它进程所占用,则此请求被阻塞,但对它对已获得的资源保持不放;
(3)不可抢占条件:进程已获得的资源,在未使用完之前,不能被剥夺,只能由使用者在使用完后释放;
(4)循环等待条件:在发生死锁时,必然存在一个进程—资源的循环链。即进程集合{P1、P2、…、Pn}中的P1正在等待一个P2占用的资源,P2正在等待一个P3占用的资源,……、Pn正在等待一个P1占用的资源。
处理死锁方法
可归结为四种:
(1)预防死锁:通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来预防发生死锁。 缺点:可能导致系统资源利用率和系统吞吐量的降低。——较严格的限制条件
(2)避免死锁:并不需要事先采取各种限制措施去破坏产生死锁的四个必要条件,而是在资源动态分配过程中,用某种方法防止系统进入不安全状态,从而避免死锁。目前在较完善的系统中,常用此方法来避免死锁。——只要较弱的限制条件
(3)检测死锁:并不事先采取任何限制措施,也不必检查系统是否已经进入不安全区,允许系统在运行过程中发生死锁,但可通过系统设置的检测机构,及时检测出死锁的发生,然后采取适当的措施,从系统中将已发生的死锁清除掉。
(4)解除死锁:是与检测死锁相配套的措施。常用的方法是撤消或挂起一些进程,以便回收一些资源,分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。——实现上难度最大。
上述四种方法,从(1)到(4)对死锁的防范程度逐渐减弱,但资源的利用率提高,并发程度提高。
由于互斥是非共享设备所必须的,不仅不能改变,还要加以保持,因此主要破坏产生死锁的后三个条件。
为破坏该条件,系统必须做到:当一个进程请求资源时,它不能持有不可抢占资源。
当一个已经保持了某些不可被抢占资源的进程,提出新资源请求而不能得到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。表示该进程的资源被抢占了,从而破坏条件。
有两种实现方法:
方法一:当进程Pi申请r类资源时,检查有无可分配的r资源,有则分配给Pi;否则将Pi占有的资源全部可被抢占,也就相当于全部隐性释放进入等待状态;
方法二:当Pi申请r时,检查有无可分配的r资源,有则分配;否则检查占有r资源的进程Pj。若Pj处于等待资源状态,则剥夺Pj的r分给Pi;若Pj没有等待资源,则置Pi于等待资源状态 (此时Pi原占有的资源可能被剥夺)
采用有序资源分配策略:
将所有的系统资源按类型进行线性排队,并赋予不同的序号;
规定所有进程对资源的请求应严格按资源序号递增顺序提出。
优点:较之其他方法资源利用率高,系统吞吐量大。
缺点:(1)为系统中各种资源类型分配序号时,必须相对稳定,从而限制了新设备的增加;
(2)会出现作业使用的资源顺序与系统规定的顺序不同的情况,造成资源的浪费。
避免死锁同样属于事先预防的策略,但该策略是在资源动态分配过程中防止系统进入不安全状态,而不是破坏必要条件。该方法限制条件较弱,可能获得较好的系统性能,此法目前常用。
银行家算法原型:为保证银行发放现金贷款时,可以满足所有客户要求,做出以下约束:①每个客户必须预先说明自己所要求的最大资金量;②每个客户每次提出部分资金量申请和获得分配;③如果银行满足了某客户对资金的最大需求量,那么,客户在资金运作后,应在有限时间内全部归还银行。
在OS中实现银行家算法:每一个新进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型的最大单元数,其数目不应该超过系统所拥有的的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配。若有,则再进一步计算,分配这些资源后,系统是否会处于不安全状态。不会则分配,否则让进程等待。
银行家算法中的数据结构
(1)可利用资源向量Available
是一个含有m个元素的数组,其中每一个元素代表一类可用资源数目,m是资源种类数。其初始值是系统中所配置的该类全部可用资源的数目,其数值动态变化。
(2)最大需求矩阵Max
是一个n×m矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求数。
(3)分配矩阵Allocation
也是一个n×m矩阵,它定义了系统中每一类资源当前已分配给每一个进程的资源数。
(4)需求矩阵Need
也是一个n×m矩阵,用于表示每个进程尚需的各类资源数。
关系:Need [ i,j ] = Max [ i,j ] – Allocation [ i,j ]
银行家算法
设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
①若Requesti[j]≤Need[i,j],转向步骤②;否则认为出错,因为它需要的资源数已超过它所宣布的最大值。
②若Requesti[j]≤Available[j],转向步骤③;否则表示表示尚无足够资源,Pi须等待。
③系统试探着把资源分配给进程Pi,并修改下面的数值:
Available[j] = Available[j] - Requesti[j]
Allocation[i,j] = Allocation[i,j] + Requesti[j]
Need[i,j] = Need[i,j] - Requesti[j]
④系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才真正将资源分配给进程Pi,以完成本次分配;否则,将本次资源分配作废,恢复原来的资源分配状态,让进程Pi等待(阻塞)。
银行家算法例子
例1.假定系统中有五个进程{P0, P1, P2, P3, P4}和三类资源{A, B, C},各种资源的数量分别为10、5、7,在T0时刻的资源分配情况如图所示
(1)T0时刻的安全性;解:
(2)P1请求资源:Request1(1,0,2); 解:
若系统既不采用死锁预防措施,也未配有死锁避免算法。系统提供两种算法:
①死锁检测算法:检测系统状态,以确定系统中是否发生了死锁
②死锁解除算法:当认定系统已发生思索,利用该算法可将系统从死锁状态解脱出来。
为了能对系统检测是否死锁,系统中必须:①保存有关资源的请求和分配信息②提供一种算法,利用这些信息检测。
(1)在资源分配图中,找到既不阻塞又不是孤点的进程 Pi (即找出一条有向边与它相连,且该有向边对应资源的申请数量小于等于系统中已有空闲资源数量)。消去它所有的请求边和分配边,使之成为孤立的结点。
在这里要注意一个问题,判断某种资源是否有空闲,应该用它的资源数量减去它在资源分配图中的出度。
(2)进程 Pi 所释放的资源,可以唤醒某些因等待这些资源而阻塞的进程,原来的阻塞进程可以变为非阻塞进程。根据(1)中的方法进行一系列
简化后,若能消去图中所有的边,则称该图是可完全简化的。
S为死锁的条件是:当且仅当 S 状态的资源分配图是不可完全简化的,该条件为死锁定理。
(1)、资源剥夺法。挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处 资源匮乏的状态。
(2)、撤销进程法。强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程优先级和撤销进程代价的高低进行。
(3)、进程回退法。让一(或多)个进程回退足以回避死锁的地步,进程回退时自愿释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。