操作系统-第七章-死锁

一、死锁概念

死锁问题

  • 在多道程序环境下,一组处于等待状态的进程,其中每一个进程都持有资源,并且等待着由这个组其他进程所持有的资源,那么该组等待进程有可能再也无法改变其状态
  • \(\color{green}{死锁与饥饿的概念辨析:}\)
    • \(\color{green}{两个以上进程,需要外力介入才能终止}\)
    • \(\color{green}{单个进程,待到某个条件才可继续运行}\)
  • \(\color{red}{所有死锁进程如无外力的介入,都无法往前推进}\)
  • 原因
    • 竞争互斥资源(最本质原因)
    • 进程推进不当
    • 系统有两个磁带设备
    • 进程P1和P2个占有一个磁带设备并且实际需要两个磁带
    • 此时P1和P2进程均死锁

系统模型

  • 资源类型:CPU周期、内存空间、文件、I/O设备
    • 形式化表示为:R1,R2,.....,Rm
  • 每一种资源Ri有Wi种实例
  • 每一个进程通过如下顺序来使用资源
    • 申请资源
      • 动态申请资源:在进程运行过程中申请所有资源(常用方法)
      • 静态申请资源:在进程运行前一次申请所有资源
    • 使用资源
    • 释放资源

二、死锁特征

必要条件

  • 四个条件同时出现,死锁将会发生
  • \(\color{red}{互斥}\):至少有一个资源必须处于非共享模式,即一次只有一个进程可以使用
  • \(\color{red}{占有并等待}\):一个至少持有一个资源的进程等待获得额外的由其他进程所持有的资源
  • \(\color{red}{非抢占}\):资源不能被抢占,即一个资源只有当持有它的进程完成任务后自动释放
  • \(\color{red}{循环等待}\):一组等待资源的进程{P0,P0,...,Pn}之间存在循环等待现象,即P0等待P1占有的资源,P1等待P2占有的资源,...,Pn-1等待Pn占有的资源,Pn等待P0占有的资源
  • 循环等待条件意味着占有并等待条件,这样四个条件并不完全独立

资源分配图

  • 一个顶点的集合V和边的集合E
  • V被分为两个部分
    • P={P1,P2,...,Pn},含有系统中全部的进程
    • R={R1,R2,...,Rm},含有系统中全部的资源
  • 申请边:有向边Pi->Rj,表示进程Pi申请了资源Rj的一个实例
  • 分配边:有向边Rj->Pi,表示资源Rj的一个实例分配给进程Pi
    • 有环有死锁的资源分配图
    • 有环但没有死锁的资源分配图
  • 结论
    • 如果资源分配图没有环,那么系统就不处于死锁状态
    • 如果图有环,那么系统可能处于死锁状态⇒
      • 如果每一种资源类型只有一个实例,那么死锁一定发生
      • 如果一种资源类型有多个实例,则可能死锁

三、处理死锁的方法

  • 使用协议来预防或避免死锁,确保系统永远不会进入死锁状态
    • 死锁预防(静态)
    • 死锁避免(动态)
  • 允许系统进入死锁状态,然后检测它,并加以恢复系统
    • 死锁检测
    • 死锁恢复
  • 忽略这个问题,假装系统中从未出现过死锁
    • 这个方法被大部分的操作系统采用,包括UNIX、Window
    • 需要应用程序的开发人员自己来处理死锁
    • 虚拟化技术,虚拟为共享设备

四、死锁预防

  • 一组方法,只要确保至少一个必要条件不成立,就能预防死锁
  • \(\color{red}{抑制死锁发生的必要条件}\)
  • 操作:通过限制资源申请的方法来预防死锁
    • 降低了设备使用率和系统吞吐量

互斥

  • 不方便改变,一般为资源属性
  • 非共享资源(互斥资源),必须要有互斥条件
  • 共享资源,不涉及死锁
  • 现代操作系统中的虚拟化技术,将互斥资源改造为共享资源
  • 如果系统中存在互斥资源,不能改变这个条件来预防死锁

占有并等待

  • 必须保证进程申请资源的时候没有占有其他资源
  • 静态分配策略
  • 协议1:要求进程在执行前一次性申请全部的资源
  • 协议2:进程只有没有占有资源时才可以分配资源
  • 资源利用率低,因为许多资源可能已分配,但是很长时间没有被使用
  • 可能出现饥饿

非抢占

  • 如果一个进程的申请没有实现,它要释放所有占有的资源(被抢占)
  • 被抢占(先占)的资源放入进程等待资源列表中
  • 进程在重新得到旧的资源的时候可以重新开始
  • 这个协议通常用于状态可用保存和恢复的资源,如CPU寄存器和内存。一般不适用于其他资源,如互斥锁和信号量

循环等待

  • 对所有的资源类型排序进行总排序,并且要求进程按照递增顺序申请资源
  • 设计一个完全排序方法并不能防止死锁,而要靠应用程序员来按照顺序编写程序
    • 设计操作系统时,顺序就已定好,电脑外设越来越多,需要充分考虑编号
  • 各资源类型的序号确定也是至关重要的,要按照系统内部资源使用的正常顺序定义
  • 某些软件可以用来验证是否按顺序来获取锁的,如果不按顺序申请且可能出现死锁,那么这些软件会给出适当警告
  • 如果能动态的获取锁,那么制定一个加锁的顺序并不保证死锁的预防

五、死锁避免

  • 事先获得有关进程申请资源和使用资源的额外信息来决定是否分配资源
  • 每次申请要求系统考虑现有可用资源、现已分配给每个进程的资源和每个进程将来申请与释放的资源,以决定申请是否满足,从而避免死锁发生的可能性
  • \(\color{red}{需要系统有一些额外的信息}\)
    • 一个简单而有效的模型要求
      • 每一个进程声明它所需要的资源的最大数
    • 死锁避免算法动态检查资源分配状态以确保循环等待条件不可能成立
    • 资源分配状态是由\(\color{red}{可用的与已分配的资源数,和进程所需的最大资源量}\)决定的

安全状态

  • 安全状态:如果系统能按照某个顺序为每个进程分配资源并能避免死锁,那么系统处于安全状态
  • 不安全状态:如果存在一个安全序列,系统处于安全状态,否则系统处于不安全状态
  • 安全序列
    • 进程序列<P1,P2,...,Pn>是安全的,如果每一个进程Pi所申请的可以被满足的资源数加上其他进程所持有的该资源数小于系统总数
      • 如果Pi需要的资源不能马上获得,那么Pi等待直到所有的Pi-1进程结束
      • 当Pi-1结束后,Pi获得所需的资源,执行、返回资源、结束
      • 当Pi结束后,Pi+1获得所需的资源执行,依此类推
  • 如果不存在安全序列,那么系统状态就是非安全的
  • 结论
    • 如果一个系统在安全状态,就没有死锁
    • 如果一个系统不是处于安全状态,就有可能死锁
    • 避免 ⇒ 确保系统永远不会进入不安全状态
      • 避免算法定义:即确保系统始终处于安全状态。最初,系统处于安全状态。当有进程申请一个可用资源时,系统应确定:这一个资源申请是可以立即分配,还是应让进程等待。只有在分配后系统仍处于安全状态,才能允许申请。

资源分配图算法

  • \(\color{red}{单实例资源}\)
  • 需求边Pi->Rj:Pi可能以后需要申请Rj资源,用虚线表示
  • Pi申请Rj资源,需求边转换为请求边
  • 请求边在资源分配后转换为分配边
  • 资源释放后,分配边转换为需求边
  • 算法
    • 假设Pi申请Rj资源
    • 请求能满足的前提是:把请求边转换为分配边后不会导致环存在
    • 如果没有环存在,那么资源的分配会使得系统处于安全状态;如果有环存在那么分配会导致系统处于非安全状态,在这种情况下,进程Pi应等待资源申请


银行家算法

  • \(\color{red}{多实例资源}\)
  • 每一个进程必须事先声明使用的最大量
  • 当一个进程请求资源,它可能要等待
  • 当一个进程得到所有的资源,它必须在有限的时间释放它们
  • 算法的数据结构
安全算法
  • Work为当前可用资源数
  • 小于等于符号需要对每个分量进行判断
  • 安全序列不唯一
  • 算法可能需要m*n2数量级的操作


资源请求算法


六、死锁检测和恢复

死锁检测

每一种资源类型只有一个实例
  • 维护等待图
    • 节点是进程
    • 从资源图中,删除所有资源类型节点,合并适当边,就可以得到等待图
    • Pi->Pj表明Pi在等待 Pj
  • 定期调用算法来检查是否有环
  • 一个检查图中是否有环的算法需要n的操作来进行,n为图中的节点数,即进程数

一个资源类型的多个实例
  • 算法的数据结构
  • 检测算法
    • 进程拥有资源才可能死锁,没有资源不会死锁,参与死锁的进程都有子资源


  • 检测算法的用法
    • 何时及多长时间的调用取决于
      • 死锁可能发生的频度
      • 有多少进程可能需要被回滚(每一个独立的环需要一个)
    • 每个请求都调用
      • 极端情况下,每次请求不能立即满足时,调用死锁检测算法
    • 不太高的频率
      • 每小时一次,或者CPU使用率低于40%时

死锁恢复

发现死锁后的措施
  • 人工处理
  • 自动恢复
自动恢复
  • 进程终止
    • 较多进程使用
    • 中断所有的死锁进程(代价大,进程可能需要重新计算)
    • 一次中断一个进程直到死锁环消失(开销相当大,每次终止一个进程,都会调用死锁检测算法,以确定是否仍有进程处于死锁)
    • 终止一个进程并不简单(如果进程正在更新文件,那么终止它会使文件处于不正确的状态)
    • 如果采用了部分终止,应该选择怎样的中断顺序?类似于CPU调度,是策略决策
      • 进程的优先级
      • 进程需要计算多长时间,以及需要多长时间结束
      • 进程使用的资源
      • 进程完成还需要多少资源
      • 多少个进程需要被中断
      • 进程是交互的还是批处理
  • 抢占资源
    • 把抢占的资源分配给其他进程使用,直到死锁循环被打破为止
      • 选择一个牺牲品:最小化代价(包含所拥有的资源数、运行到现在的时间等)
      • 回退:返回到安全的状态,然后重新开始进程(并不是所有进程都可以回滚;有些资源不可以抢占)
      • 饥饿:同样进程的可能总是被选中(在代价因素中加入回滚次数)

posted @ 2020-11-10 20:24  方知有  阅读(474)  评论(0编辑  收藏  举报