操作系统基础知识整理

9.2 死锁预防与避免

2017-06-03  本文已影响39人  saviochen

死锁预防

预防死锁的方法是破坏死锁必要条件中的一个。由于互斥条件是由设备的固有特性决定的,如打印机等临界资源只能互斥使用。故只能通过破坏其他条件来实现预防死锁:

1)破坏不剥夺条件

规定进程逐个提出资源请求。当一个已经保持某些资源的进程再提出新资源请求而无法立刻被满足时,必须释放它已经保持了的所有资源,待将来需要时重新申请。进程在运行过程中,已占有的资源可能被暂时释放,从而摒弃了“不剥夺”条件。

该策略实现起来比较复杂,释放已获得的资源可能造成前一阶段工作的失效,反复地申请和释放资源会增加系统开销,降低系统吞吐量。这种方法常用于状态易于保存和恢复的资源,如CPU的寄存器及内存资源,一般不能用于打印机之类的资源。

2) 破坏请求和保持条件

釆用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。

这种方式实现简单,但缺点也显而易见,系统资源被严重浪费,其中有些资源可能仅在运行初期或运行快结束时才使用,甚至根本不使用。而且还会导致“饥饿”现象,当由于个别资源长期被其他进程占用时,将致使等待该资源的进程迟迟不能开始运行。

3) 破坏循环等待条件

为了破坏循环等待条件,可釆用顺序资源分配法。首先给系统中的资源编号,规定每个进程,必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源Ri,则该进程在以后的资源申请中,只能申请编号大于Ri的资源。

这种方法存在的问题是,编号必须相对稳定,这就限制了新类型设备的增加;尽管在为资源编号时已考虑到大多数作业实际使用这些资源的顺序,但也经常会发生作业使甩资源的顺序与系统规定顺序不同的情况,造成资源的浪费;此外,这种按规定次序申请资源的方法,也必然会给用户的编程带来麻烦。

死锁避免

避免死锁同样是属于事先预防的策略,但并不是事先釆取某种限制措施破坏死锁的必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁。这种方法所施加的限制条件较弱,可以获得较好的系统性能

1 系统安全状态

避免死锁同样是属于事先预防的策略,但并不是事先釆取某种限制措施破坏死锁的必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁。这种方法所施加的限制条件较弱,可以获得较好的系统性能。

所谓安全状态,是指系统能按某种进程推进顺序( P1, P2, ..., Pn),为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺序地完成。此时称 P1, P2, ..., Pn 为安全序列。如果系统无法找到一个安全序列,则称系统处于不安全状态。

并非所有的不安全状态都是死锁状态,但当系统进入不安全状态后,便可能进入死锁状态反之,只要系统处于安全状态,系统便可以避免进入死锁状态。

2 银行家算法

银行家算法是最著名的死锁避免算法。它提出的思想是:把操作系统视为银行家,操作系统管理的资源类比于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。操作系统按照银行家制定的规则为进程分配资源。

2.1 分配过程描述
  1. 进程首次申请资源时,要测试其对资源的最大需求量,若现存资源可满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。

  2. 当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量。若超过则拒绝分配资源,若未超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前的申请量分配资源,否则也要推迟分配。

2.2 数据结构描述

可利用资源矢量Available:含有m个元素的数组,其中的每一个元素代表一类可用的资源数目。Available[j]=K,则表示系统中现有Rj类资源K个。

最大需求矩阵Max:为n*m矩阵,定义了系统中n个进程中的每一个进程对m类资源的最大需求。Max[i, j]=K,则表示进程i需要Rj类资源的最大数目为K。

分配矩阵Allocation:为n*m矩阵,定义了系统中每一类资源当前已分配给每一进程的资源数。Allocation[i, j]= K,则表示进程i当前已分得Rj类资源的数目为K。

需求矩阵Need:为n*m矩阵,表示每个进程尚需的各类资源数。Need[i, j]=K,则表示进程i还需要Rj类资源的数目为K。

上述三个矩阵间存在下述关系:
Need[i, j] = Max[i, j] - Allocation[i, j]

2.3 银行家算法描述

设Requesti是进程Pi的请求矢量,如果Requesti[j] = K,表示进程Pi需要Rj类资源K个。当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等待。

2.4 安全性算法

①设置两个矢量。工作矢量Work:表示系统可提供给进程继续运行所需的各类资源数目,它含有所个元素,在执行安全算法开始时,Work=Available; Finish:它表示系统是否有足够的资源分配给进程,使之运行完成。开始时 Finish[i]=false;当有足够资源分配给进程 Pi 时,再令 Finish[i]=true。

②从进程集合中找到一个能满足下述条件的进程:Finish[i]=false; Need[i, j]<=Work[j]; 若找到,执行下一步骤,否则,执行步骤4。

③当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

Work[j]=Work[j]+Allocation[i, j];
Finish[i]=true;
go to step <2>;

④如果所有进程的Finish[i]=tme都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

上一篇下一篇

猜你喜欢

热点阅读