第6章 死锁

  操作系统具有授权一个进程排他地访问某一种资源的能力。

1 资源

  资源:需要排他使用的对象。
  可抢占资源:可从拥有它的进程中抢占而不会引起任何副作用的资源。
  不可抢占资源:进程一旦拥有资源后,该资源不可收回,只能由进程自己释放。

  使用资源的过程:请求资源、使用资源、释放资源。

2 死锁

  死锁定义:一个进程集合中每个进程都在等待只能该集合中其他进程才能引发的事件。
  死锁的必要条件:互斥、占有和等待、不可抢占、环路等待。
  资源分配图:圆圈代表进程,方框代表资源,由方框指向圆圈的有向边代表资源分配,由圆圈指向方框的有向边代表资源请求。

  处理死锁的策略:忽略死锁、检测死锁并恢复、避免死锁、破坏死锁的必要条件。

3 鸵鸟算法

  鸵鸟算法就是忽略死锁。

4 死锁检测与恢复

4.1 每种类型一个资源的检测

  检测方法:若资源分配图中有环,则环中的进程都是死锁进程。
  算法如下

  1. 随机选择一个节点N,作为起始节点,执行下面5步。
  2. 将L初始化为空表,并清除所有有向边标记。
  3. 将当前节点添加到L的尾部,并检查该节点是否在L中已出现两次,若是则死锁,算法结束,否则进行下一步。
  4. 从给定的节点开始,检测是否存在没有标记的从该节点触发的有向边,如果存在则进行第5步,否则进行第6步。
  5. 随机选取一条有向边并标记它,顺着这条边找到新的节点,回到第3步。
  6. 如果这个节点是起始节点,则不存在环,算法结束,否则意味着是条死路,移走该节点,返回前一个节点,作为当前节点,回到第三步。

4.2 每种类型多个资源的检测

  设ei表示i类资源的总量,ai表示i类资源可利用数量。cij表示进程i持有j类资源的数量,rij表示进程i请求j类资源的数量,E向量为现有资源,A向量为可用资源。C矩阵表示资源分配,R矩阵表示资源请求。设向量A小于等于向量B的条件是A的每一个分量小于等于B中对应分量。
  算法如下

  1. 每个进程初始都未标记。
  2. 寻找一个没有标记的进程,要求其R矩阵的第i行向量小于或等于A。
  3. 如果找到这样的进程,那么将C矩阵的第i行向量加到A中,标记该进程,转到第1步。
    4.如果未找到,则算法终止。
  4. 算法终止时,没有标记过的进程就是死锁进程。

4.3 通用的检测算法

  在资源分配图中,找到一个既不阻塞也不孤立的的进程,消除其请求边和分配边,使之成为孤立的点。重复这个过程,使得所有的进程都成为孤点,如果不能实现,则存在死锁。

4.4 从死锁中恢复

  利用抢占恢复——要求资源可抢占
  利用回滚恢复——要求对进程周期性的设置回滚点
  利用杀死进程恢复——要求杀死环中的进程或者环外的重新运行不会有副作用的进程。

5 死锁避免

  死锁避免是基于安全状态。
  安全状态:若没有死锁发生,并且即使所有进程突然请求对资源的最大需求,仍然存在某种调度次序能够使得每一个进程运行完毕。否则,则是不安全状态
  不安全状态不是死锁

5.1 单种资源的银行家算法

  银行家算法:对每一个请求进行检查,检查如果满足该请求后是否是安全的,若是则满足该请求,否则推迟满足该请求。

5.2 多种资源的银行家算法

  设ei表示i类资源的总量,ai表示i类资源可利用数量。cij表示进程i持有j类资源的数量,rij表示进程i请求j类资源的数量,E向量为现有资源,A向量为可用资源。C矩阵表示资源分配,R矩阵表示资源请求。设向量A小于等于向量B的条件是A的每一个分量小于等于B中对应分量。
  算法如下

  1. 检查资源请求矩阵R中是否有一行小于等于向量A,如果没有则存在死锁。如果有则进行第二步。
  2. 将该进程标记为终止,并将C矩阵中对应向量加到A中。
  3. 重复1、2步,直到所有进程标记为终止,则初始状态是安全的。否则,则发生死锁,初始状态不是安全的。

6 死锁预防

  破话互斥条件——假脱机技术。
  破坏持有并等待条件——一开始就请求所需全部资源,或者先释放持有资源,再一次请求所需全部资源。
  破坏不可抢占条件——虚拟化。
  破坏环路等待条件——进程任意时刻只能占有一种资源,或者所有请求必须按照资源编号且按升序提出,或者不允许进程请求比当前持有资源编号低的资源。

7 其它问题

  两阶段加锁:第一阶段先对所需资源加锁,第二阶段进行操作。在第一阶段加锁时如果遇到已经加锁的资源,则需要释放所有由该进程加锁的资源,然后重新开始。否则,则可能由于重复加锁而死锁。
  通信死锁:进程A向进程B发送消息,然后阻塞直到B回复,B阻塞直到收到A的消息然后回复A。如果A的消息丢失,则两个进程无线等待成为死锁。解决办法:超时机制。
  活锁:当进程无法获取下一个资源时,就释放持有的资源,等待一段时间后,再次尝试。如果有两个进程同时做相同的操作,那么相同的步调将导致双方都停止推进。解决办法:等待随机长的时间。
  饥饿:由于某种策略导致某个进程永远 无法执行。解决办法:先来先服务。

猜你喜欢

转载自blog.csdn.net/liao20081228/article/details/78722619