死锁

  • 死锁问题
  • 系统模型
  • 死锁特征
  • 死锁处理方法
    • Deadlock Prevention(死锁预防)
    • Deadlock Avoidance(死锁避免)
    • Deadlock Detection(死锁检测)
    • Recovery from Deadlock(死锁恢复)

 

死锁出现的情况

一组阻塞的进程持有一种资源等待获取另一个进程所占有的一个资源。
例子

  • 系统有2个磁带驱动器
  • P1和P2各有一个,都需要另外一个。

 

死锁的系统模型

资源类型R1,R2,. . .,Rm
CPU cycles,memory space,I/O devices每个资源类型Ri有Wi实例。
每个进程使用资源如下:

  • request/get <-- free resource
  • use/hold <-- requested/used resource
  • release <-- free resource

可重复使用的资源

  • 在一个时间只能一个进程使用且不能被删除
  • 进程获得资源,后来释放由其他进程重用
  • 处理器,I/0通道,主和副存储器,设备和数据结构,如文件,数据库和信号量
  • 如果每个进程拥有一个资源并请求其它资源,死锁可能发生

使用资源

  • 创建和销毁
  • 在I/O缓冲区的中断,信号,消息,信息
  • 如果接收消息阻塞可能会发生死锁
  • 可能少见的组合事件会引起死锁

 

资源分配图:一组顶点V和边E的集合

V有两种类型:

P= (P,P,…,P,),集合包括系统中的所有进程。

  • R= (R,R,…,R),集合包括系统中的所有资源类型。

requesting/claiming edge - directed edge Pi-->Rj

assignment/holdingedge - directed edge Rj-> Pi;

 

有死锁的情况

注意:有循环不一定出现死锁

基本情况

如果图中不包含循环==>没有死锁。

如果图中包括循环==>

  • 如果每个资源类只有一个实例,那么死锁。
  • 如果每个资源类有几个实例,可能死锁。

 

死锁特征

如果下面四个条件同时成立,死锁可能出现

  • 互斥:在一个时间只能有一个进程使用资源。
  • 持有并等待:进程保持至少一个资源正在等待获取其他进程持有的额外资源。
  • 无抢占:一个资源只能被进程自愿释放,进程已经完成了它的任务之后。
  • 循环等待:存在等待进程集合{P0,P1,...,PN) ,PO正在等待P1所占用的资源,Pl正在等待P2占用的资源,...,PN-1在等待PN所占用资源,PN正在等待P0所占用的资源。

这四个条件是死锁出现的必要不充分条件

 

死锁的处理方法

  • 确保系统永远不会进入死锁状态。
  • 运行系统进入死锁状态,然后恢复。
  • 忽略这个问题,假装系统中从来没有发生死锁;用于大多数操作系统,包括UNIX。

 

死锁预防

限制申请方式

互斥–共享资源不是必须的,必须占用非共享资源。
占用并等待–必须保证当一个进程请求的资源,它不持有任何其他资源。

  • 需要进程请求并分配其所有资源,它开始执行之前或允许进程请求资源仅当进程没有资源。
  • 资源利用率低;可能发生饥饿。

无抢占

  • 如果进程占有某些资源,并请求其它不能被立即分配的资源,则释放当前正占有的资源
  • 被抢占资源添加到资源列表中
  • 只有当它能够获得旧的资源以及它请求新的资源,进程可以得到执行

循环等待–对所有资源类型进行排序,并要求每个进程按照资源的顺序进行申请。

 

死锁避免

需要系统具有—些额外的先验信息提供。

  • 最简单和最有效的模式是要求每个进程声明它可能需要的每个类型资源的最大数目。
  • 资源的分配状态是通过限定提供与分配的资源数量,和进程的最大需求。
  • 死锁避免算法动态检查的资源分配状态,以确保永远不会有一个环形等待状态。

当一个进程请求可用资源,系统必须判断立即分配是否能使系统处于安全状态。
系统处于安全状态指:针对所有进程,存在安全序列。

序列<P1,P2,...,PN>是安全的:针对每个Pi,Pi要求的资源能够由当前可用的资源+所有的Pj;持有的资源来满足,其中j<i。

  • 如果Pi,资源的需求不是立即可用,那么Pi可以等到所有Pj完成。
  • 当Pi完成后,Pi+1.可以得到所需要的资源,执行,返回所分配的资源,并终止。
  • 用同样的方法,Pi+2,Pi+3和Pn能获得其所需的资源。

如果系统处于安全状态-=>无死锁。

如果系统处于不安全状态-==>可能死锁。

避免死锁:确保系统永远不会进入不安全状态。

检测流程

Clain edge Pi一-Rj表示进程PJ请求资源的Rj;由虚线表示。
当一个进程请求资源,Claim edge转换为request edge , 。
当资源被进程释放,assignmentedge转换为claim edge。
在系统中资源必须要求先验。

 

 

银行家算法

前提条件

  • 多个实例。
  • 每个进程都必须能最大限度地利用资源。
  • 当一个进程请求一个资源,就不得不等待。
  • 当一个进程获得所有的资源就必须在一段有限的时间释放它们。

基于上述前提条件,银行家算法通过尝试寻找允许每个进程获得的最大资源并结束(把资源返还给系统)的进程请求的一个理想执行时序,来决定一个状态是否是安全的。
不存在这满足要求的执行时序的状态都是不安全的。

 

n=进程数量,m=资源类型数量。

  • Max(总需求量): n×m矩阵.。如果Max [i,j] = k,表示进程P;最多请求资源类型R,的k个实例。
  • Available (剩余空闲量)︰长度为m的向量。如果Available [j]= k,有k个类型R,的资源实例可用。
  • Allocation(已分配量): n×m矩阵。如果Allocation[i,j]= k,则P;当前分配了k个Rj的实例。
  • Need(未来需要量): n×m矩阵。如果Need[i,j] = k,则Pi可能需要至少k个Rj实例完成任务。

Need [i,j] = Max[i,j]一Allocation [i,j]

寻找安全序列的流程

 

 

 

 

 

死锁检测和死锁恢复

 

  • 允许系统进入死锁状态
  • 死锁检测算法
  • 恢复机制

检测依据

每个资源类型单一实例

  • Maintain wait-for graph定期调用检测算法来搜索图中是否存在循环
    • 节点是进程。
    • Pi=> Pj :Pi等待Pj
  • 算法需要n2次操作,n是图中顶点的数

资源类型的几个实例
数据结构

  • Available:长度为M的向量表示每种类型可用资源的数量。
  • Allocation:一个n×m矩阵定义了当前分配给各个进程每种类型资源的数量。如果Allocation[i , j]=k,进程Pi拥有资源Rj的k个实例。
  • Request:一个nxm矩阵表示各进程的当前请求.。如果Request [i , j] = k,表示进程Pi请求k个资源Rj的实例。

 

 

 

 

算法需要0(m x P2)操作检测是否系统处于死锁状态

检测算法使用的一些问题

何时、使用什么样的频率来检测依赖于︰

  • 死锁多久可能会发生?
  • 多少进程需要被回滚?

one for each disjoint cycle

如果检测算法多次被调用,有可能是资源图有多个循环,所以我们无法分辨出多个可能死锁进程中的哪些“造成”死锁。

 

死锁恢复

 

  • 终止所有的死锁进程
  • 在一个时间内终止一个进程直到死锁消除
  • 终止进程的顺序应该是
    • 进程的优先级
    • 进程运行了多久以及需要多少时间才能完成
    • 进程占用的资源
    • 进程完成需要的资源
    • 多少进程需要被终止
    • 进程是交互还是批处理

 

  • 选择一个受害者–最小的成本。
  • 回滚–返回到一些安全状态,重启进程到安全状态。
  • 饥饿–同一进程可能一直被选作受害者,包括回滚的数量。

 

 

IPC(进程间通信)

  • 概述
    • 通信模型
    • 直接及间接通信
    • 阻塞与非阻塞
    • 通信链路缓冲
  • 信号
  • 管道
  • 消息队列
  • 共享内存

 概述

 

  • 进程通信的机制及同步
  • 不使用共享变量的进程通信
  • IPC facility提供2个操作:
    • scnd(messago)-消息大小固定或者可变
    • receive(message)
  • 如果Р和О想通信,需要:
    • 在它们之间建立通信链路
    • 通过send/receive交换消息
  • 通信链路的实现
    • 物理(例如,共享内存,硬件总线)
    • 逻辑(例如,逻辑属性)

进程通信方法图解

 

直接通信
进程必须正确的命名对方:

  • send (P, message)-发送信息到进程
  • Preceive(Q, message)-从进程Q接受消息

通信链路的属性

  • 自动建立链路
  • 一条链路恰好对应一对通信进程
  • 每对进程之间只有一个链接存在
  • 链接可以是单向的,但通常为双向的

间接通信
定向从消息队列接收消息

  • 每个消息队列都有一个唯一的ID
  • 只有它们共享了一个消息队列,进程才能够通信

通信链路的属性

  • 只有进程共享一个共同的消息队列,才建立链路
  • 链接可以与许多进程相关联
  • 每对进程可以共享多个通信链路
  • 连接可以是单向或双向

操作

  • 创建一个新的消息队列
  • 通过消息队列发送和接收消息
  • 销毁消息队列

原语的定义如下:

  • send(A,message)-发送消息到队列A
  • receive(A,message) -从队列A接受消息

 

消息传递可以是阻塞或非阻塞

阻断被认为是同步的

  • Blocking send has the sender block until themessage is received
  • Blocking receive has the receiver block until amessage is available

非阻塞被认为是异步的

  • Non-blocking send has the sender send themessage and continue
  • Non-blocking receive has the receiver receive avalid message or null

 

队列的消息被附加到链路,可以是以下3种方式之一:

1.0容量- 0 messages
发送方必须等待接收方(rendezvous)

2.有限容量-n messages的有限长度
发送方必须等待,如果队列满

3.无限容量–无限长度
发送方不需要等待

 

Signal(信号)

  • 软件中断通知事件处理
  • Examples: SIGFPE,SIGKILL,SIGUSR1,SIGSTOP,SIGCONT

接收到信号时会发生什么

  • Catch:指定信号处理函数被调用
  • Ignore:依靠操作系统的默认操作
    • Example: Abort,memory dump,suspend or resume process
  • Mask:闭塞信号因此不会传送
    • 可能是暂时的(当处理同样类型的信号)

不足

  • 不能传输要交换的任何数据

信号的实现

管道

 

子进程从父进程继承文件描述符

  • file descriptor 0 stdin, 1 stdout,2 stderr

进程不知道(或不关心!)从键盘,文件,程序读取或写入到终端,文件,程序。

例子: ls|more

shell:

  • 创建管道
  • 为ls创建一个进程,设置stdout为管道写端
  • 为more创建一个进程,设置stdin为管道读端

消息队列

消息队列按FIFO的来管理消息

  • Message :作为一个字节序列存储
  • Message Queues:消息数组
  • FIFO & FILO configuration

 

共享内存

进程

  • 每个进程都有私有地址空间
  • 在每个地址空间内,明确地设置了共享内存段

优点

  • 快速、方便地共享数据

不足

  • 必须同步数据访问

共享内存特点

  • 最快的方法
  • —个进程写另外一个进程立即可见
  • 没有系统调用干预
  • 没有数据复制
  • 不提供同步
    • 由程序员提供同步