操作系统 第二部分 进程管理(五)

5) 死锁:死锁的基本概念,死锁定理、死锁预防、死锁避免与处理死锁的基本方法、银行家算法。

3.5  产生死锁的原因和必要条件

3.5.1 产生死锁的原因

产生死锁的原因可归结为如下两点:
  (1) 竞争资源。当系统中供多个进程共享的资源如打印机、公用队列等,其数目不足以满足诸进程的需要时,会引起诸进程对资源的竞争而产生死锁。
  (2) 进程间推进顺序非法。进程在运行过程中,请求和释放资源的顺序不当,也同样会导致产生进程死锁。
  1.竞争资源引起进程死锁
  1) 可剥夺和非剥夺性资源
  可把系统中的资源分成两类,一类是可剥夺性资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺。例如,优先权高的进程可以剥夺优先权低的进程的处理机。又如,内存区可由存储器管理程序把一个进程从一个存储区移到另一个存储区,此即剥夺了该进程原来占有的存储区。甚至可将一个进程从内存调出到外存上。可见,CPU和主存均属于可剥夺性资源。另一类资源是不可剥夺性资源,当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。
  2) 竞争非剥夺性资源
  在系统中所配置的非剥夺性资源,由于它们的数量不能满足诸进程运行的需要,会使进程在运行过程中,因争夺这些资源而陷入僵局。例如,系统中只有一台打印机R 1 和一台磁带机R 2 ,可供进程P 1 和P 2 共享。假定P 1 已占用了打印机R 1 ,P 2 已占用了磁带机R 2 。此时,若P 2 继续要求打印机,P 2 将阻塞;P 1 若又要求磁带机,P 1 也将阻塞。于是,在P 1与P 2 之间便形成了僵局,两个进程都在等待对方释放出自己所需的资源。但它们又都因不能继续获得自己所需的资源而不能继续推进,从而也不能释放出自己已占有的资源,以致进入死锁状态。为便于说明,我们用方块代表资源,用圆圈代表进程,见图3-13 所示。当箭头从进程指向资源时,表示进程请求资源;当箭头从资源指向进程时,表示该资源已被分配给该进程。从中可以看出,这时在P 1 、P 2 及R 1 和R 2 之间已经形成了一个环路,说明已进入死锁状态。
  在这里插入图片描述
  上述的打印机资源属于可顺序重复使用型资源,称为永久性资源。还有一种是所谓的临时性资源,这是指由一个进程产生,被另一进程使用一短暂时间后便无用的资源,故也称之为消耗性资源,它也可能引起死锁。图3-14示出了在进程之间通信时形成死锁的情况。图中S 1 、S 2 和S 3 是临时性资源。进程P 1 产生消息S 1 ,又要求从P 3 接收消息S 3 ;进程P 3 产生消息S 3 ,又要求从进程P 2 接收其所产生的消息S 2 ;进程P 2 产生消息S 2 ,又需要接收进程P 1 所产生的消息S 1 。如果消息通信按下述
顺序进行:
P 1 : …Release(S 1 ); Reqaest(S 3 ); …
P 2 : …Release(S 2 ); Request(S 1 ); …
P 3 : …Release(S 3 ); Request(S 2 ); …
并不可能发生死锁,但若改成下述的运行顺序:
P 1 : …Request(S 3 ); Release(S 1 ); …
P 2 : …Request(S 1 ); Release(S 2 ); …
P 3 : …Request(S 2 ); Release(S 3 ); …
则可能发生死锁。
在这里插入图片描述
2 .进程推进顺序不当引起死锁
  由于进程在运行中具有异步性特征,这就可能使上述P 1 和P 2 两个进程按下述两种顺序向前推进。
 1) 进程推进顺序合法
  在进程P 1 和P 2 并发执行时,如果按下述顺序推进:
  P 1 :Request(R 1 );Request(R 2 );
  P 1 :Releast(R 1 );Release(R 2 );
  P 2 :Request(R 2 );Request(R 1 );
  P 2 :Release(R 2 );Release(R 1 );
  在这里插入图片描述
   2) 进程推进顺序非法
  若并发进程P 1 和P 2 按曲线④所示的顺序推进,它们将进入不安全区D内。此时P 1 保持了资源R 1 ,P 2 保持了资源R 2 ,系统处于不安全状态。因为这时两进程再向前推进,便可能发生死锁。例如,当P 1 运行到P 1 :Request(R 2 )时,将因R 2 已被P 2 占用而阻塞;当P 2 运行到P 2 :Request(R 1 )时,也将因R 1 已被P 1 占用而阻塞,于是发生了进程死锁。

3.5.2 产生死锁的必要条件

虽然进程在运行过程中可能发生死锁,但死锁的发生也必须具备一定的条件。综上所述不难看出,死锁的发生必须具备下列四个必要条件。
  (1) 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求该资源,则请求者只能等待,直至占有该资源的进程用毕释放。
  (2) 请求和保持条件:指进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源又已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

3.5.3 处理死锁的基本方法

(1) 预防死锁。这是一种较简单和直观的事先预防的方法。该方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但由于所施加的限制条件往往太严格,因而可能会导致系统资源利用率和系统吞吐量降低。
  (2) 避免死锁。该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。这种方法只需事先施加较弱的限制条件,便可获得较高的资源利用率及系统吞吐量,但在实现上有一定的难度。目前在较完善的系统中常用此方法来避免发生死锁。
   (3) 检测死锁。这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,而是允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源;然后,采取适当措施,从系统中将已发生的死锁清除掉。
   (4) 解除死锁。这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤消或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。

3.6  预防死锁的方法

3.6.1 预防死锁

1.摒弃“请求和保持”条件
  在采用这种方法时,系统规定所有进程在开始运行之前,都必须一次性地申请其在整个运行过程所需的全部资源。此时,若系统有足够的资源分配给某进程,便可把其需要的所有资源分配给该进程,这样,该进程在整个运行期间便不会再提出资源要求,从而摒弃了请求条件。但在分配资源时,只要有一种资源不能满足某进程的要求,即使其它所需的各资源都空闲,也不分配给该进程,而让该进程等待。由于在该进程的等待期间,它并未占有任何资源,因而也摒弃了保持条件,从而可以避免发生死锁。
  这种预防死锁的方法其优点是简单、易于实现且很安全。但其缺点却也极其明显:首先表现为资源被严重浪费,因为一个进程是一次性地获得其整个运行过程所需的全部资源的,且独占资源,其中可能有些资源很少使用,甚至在整个运行期间都未使用,这就严重地恶化了系统资源的利用率;其次是使进程延迟运行,仅当进程在获得了其所需的全部资源后,才能开始运行,但可能因有些资源已长期被其它进程占用而致使等待该资源的进程迟迟不能运行。
  2.摒弃“不剥夺”条件
  在采用这种方法时系统规定,进程是逐个地提出对资源的要求的。当一个已经保持了某些资源的进程,再提出新的资源请求而不能立即得到满足时,必须释放它已经保持了的所有资源,待以后需要时再重新申请。这意味着某一进程已经占有的资源,在运行过程中会被暂时地释放掉,也可认为是被剥夺了,从而摒弃了“不剥夺”条件。
  这种预防死锁的方法实现起来比较复杂且要付出很大的代价。因为一个资源在使用一段时间后,它的被迫释放可能会造成前段工作的失效,即使是采取了某些防范措施,也还会使进程前后两次运行的信息不连续,例如,进程在运行过程中已用打印机输出信息,但中途又因申请另一资源未果而被迫暂停运行并释放打印机,后来系统又把打印机分配给其它进程使用。当进程再次恢复运行并再次获得打印机继续打印时,这前后两次打印输出的数据并不连续,即打印输出的信息其中间有一段是另一进程的。此外,这种策略还可能因为反复地申请和释放资源,致使进程的执行被无限地推迟,这不仅延长了进程的周转时间,而且也增加了系统开销,降低了系统吞吐量。
  3.摒弃“环路等待”条件
  这种方法中规定,系统将所有资源按类型进行线性排队,并赋予不同的序号。例如,令输入机的序号为1,打印机的序号为2,磁带机为3,磁盘为4。所有进程对资源的请求必须严格按照资源序号递增的次序提出,这样,在所形成的资源分配图中,不可能再出现环路,因而摒弃了“环路等待”条件。事实上,在采用这种策略时,总有一个进程占据了较高序号的资源,此后它继续申请的资源必然是空闲的,因而进程可以一直向前推进。
  这种预防死锁的策略与前两种策略比较,其资源利用率和系统吞吐量都有较明显的改善。但也存在下述严重问题:
  首先是为系统中各类资源所分配(确定)的序号必须相对稳定,这就限制了新类型设备的增加。
  其次,尽管在为资源的类型分配序号时,已经考虑到大多数作业在实际使用这些资源时的顺序,但也经常会发生这种情况:即作业(进程)使用各类资源的顺序与系统规定的顺序不同,造成对资源的浪费。例如,某进程先用磁带机,后用打印机,但按系统规定,该进程应先申请打印机而后申请磁带机,致使先获得的打印机被长时间闲置。
  第三,为方便用户,系统对用户在编程时所施加的限制条件应尽量少。然而这种按规定次序申请的方法,必然会限制用户简单、自主地编程。

3.6.2 系统安全状态

1.安全状态
  在避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,令进程等待。
  所谓安全状态,是指系统能按某种进程顺序(P 1 ,P 2 ,…,P n )(称〈P 1 ,P 2 ,…,P n 〉序列为安全序列),来为每个进程P i分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。
  虽然并非所有的不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,便有可能进而进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。因此,避免死锁的实质在于:系统在进行资源分配时,如何使系统不进入不安全状态。
  2 .安全状态之例
  我们通过一个例子来说明安全性。假定系统中有三个进程P 1 、P 2 和P 3 ,共有12台磁带机。进程P 1 总共要求10台磁带机,P 2 和P 3 分别要求4台和9台。假设在T 0 时刻,进程P 1 、P 2和P 3 已分别获得5台、2台和2台磁带机,尚有3台空闲未分配,如下表所示:

在这里插入图片描述
  3 .由安全状态向不安全状态的转换
  如果不按照安全序列分配资源,则系统可能会由安全状态进入不安全状态。例如,在T 0 时刻以后,P 3 又请求1台磁带机,若此时系统把剩余3台中的1台分配给P 3 ,则系统便进入不安全状态。因为此时也无法再找到一个安全序列,例如,把其余的2台分配给P 2 ,这样,在P 2 完成后只能释放出4台,既不能满足P 1 尚需5台的要求,也不能满足P 3 尚需6台的要求,致使它们都无法推进到完成,彼此都在等待对方释放资源,即陷入僵局,结果导致死锁。类似地,如果我们将剩余的2台磁带机先分配给P 1 或P 3 ,也同样都无法使它们推进到完成,因此,从给P 3 分配了第3台磁带机开始,系统便又进入了不安全状态。由此可见,在P 3 请求资源时,尽管系统中尚有可用的磁带机,但却不能分配给它,必须让P 3 一直等待到P 1 和P 2 完成,释放出资源后再将足够的资源分配给P 3 ,它才能顺利完成。

3.6.3利用银行家算法避免死锁

1.银行家算法中的数据结构
  (1) 可利用资源向量Available。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随 该 类 资 源 的 分 配 和 回 收 而 动 态 地 改 变 。 如 果Available[j]=K,则表示系统中现有R j类资源K个。
  (2) 最大需求矩阵Max。这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
  (3) 分配矩阵Allocation。这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得R j 类资源的数目为K。
  (4) 需求矩阵Need。这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要R j 类资源K个,方能完成其任务。
  上述三个矩阵间存在下述关系:
  Need[i, j]=Max[i, j]-Allocation[i, j]
  2 .银行家算法
  设Request i 是进程P i 的请求向量,如果Request i [j]=K,表示进程P i 需要K个R j 类型的资源。当P i 发出资源请求后,系统按下述步骤进行检查:
  (1) 如果Request i [j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
  (2) 如果Request i [j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,P i 须等待。
  (3) 系统试探着把资源分配给进程P i ,并修改下面数据结构中的数值:
  Available[j]:= Available[j]-Request i [j];
  Allocation[i,j]:= Allocation[i,j]+Request i [j];
  Need[i,j]:= Need[i,j]-Request i [j];
  (4) 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程P i ,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程P i 等待。
  3.安全性算法
  系统所执行的安全性算法可描述如下:
  (1) 设置两个向量:
  ① 工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work:=Available。
  ② Finish,它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]:=false;当有足够资源分配给进程时,再令Finish[i]:=true。
  (2) 从进程集合中找到一个能满足下述条件的进程:
  ① Finish[i]=false;
  ② Need[i,j]≤Work[j];若找到,执行步骤(3),否则,执行步骤(4)。
  (3) 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,应执行:
  Work[j]:= Work[j]+Allocation[i,j];
  Finish[i]:=true;
  go to step 2;
  (4) 如果所有进程的Finish[i]=true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。
  4 .银行家算法之例
  假定系统中有五个进程{P 0 ,P 1 ,P 2 ,P 3 ,P 4 }和三类资源{A,B,C},各种资源的数量分别为10、5、7,在T 0 时刻的资源分配情况如图3-16所示。
 在这里插入图片描述
  (1) T 0 时刻的安全性:利用安全性算法对T 0 时刻的资源分配情况进行分析(见图 3-17所示)可知,在T 0 时刻存在着一个安全序列{P 1 ,P 3 ,P 4 ,P 2 ,P 0 },故系统是安全的。
在这里插入图片描述
  (2)  P 1 请求资源:P 1 发出请求向量Request 1 (1,0,2),系统按银行家算法进行检查:
  ① Request 1 (1,0,2)≤Need 1 (1,2,2)
  ② Request 1 (1,0,2)≤Available 1 (3,3,2)
  ③ 系统先假定可为P 1 分配资源,并修改Available,Allocation 1 和Need 1 向量,由此形成的资源变化情况如图3-16中的圆括号所示。
  ④ 再利用安全性算法检查此时系统是否安全。如图3-18所示。 在这里插入图片描述
  (3)  P 4 请求资源:P 4 发出请求向量Request 4 (3,3,0),系
统按银行家算法进行检查:
  ① Request 4 (3,3,0)≤Need 4 (4,3,1);
  ② Request 4 (3,3,0)≤Available(2,3,0),让P 4 等待。
  (4)  P 0 请求资源:P 0 发出请求向量Requst 0 (0,2,0),系
统按银行家算法进行检查:
  ① Request 0 (0,2,0)≤Need 0 (7,4,3);
  ② Request 0 (0,2,0)≤Available(2,3,0);
  ③ 系统暂时先假定可为P 0 分配资源,并修改有关数据,如图3-19所示。
在这里插入图片描述
  (5) 进行安全性检查:可用资源Available(2,1,0)已不能满足任何进程的需要,故系统进入不安全状态,此时系统不分配资源。
  如果在银行家算法中,把P0发出的请求向量改为Request 0 (0,1,0),系统是否能将资源分配给它,请读者考虑。

3.7  死锁的检测与解除

3.7.1 死锁的检测
  当系统为进程分配资源时,若未采取任何限制性措施,则系统必须提供检测和解除死锁的手段,为此,系统必须做到:
  (1) 保存有关资源的请求和分配信息;
  (2) 提供一种算法,以利用这些信息来检测系统是否已进入死锁状态。

猜你喜欢

转载自blog.csdn.net/AnalogElectronic/article/details/88912592
今日推荐