计算机操作系统 - 死锁
文章目录
一、必要条件
互斥:每个资源要么分配给进程,要么是可用
占有与等待:已经得到某资源的线程可以再请求新的资源
不可抢占:已经分配给一个进程的资源不可被抢夺,只能等待被占有的进程显式的释放进程。
环路等待:有两个或两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源
二、处理方法
主要有以下几种方法:
-
鸵鸟策略
-
死锁检测与死锁恢复
-
死锁预防
-
死锁避免
三、鸵鸟策略
把头埋在沙子里假装什么事也没发生。
因为解决死锁的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
大多数操作系统,包括Linux、unix、windows,处理死锁问题的办法仅仅是忽略它。
四、死锁检测与死锁恢复
不试图阻止死锁,而是当检测到死锁的时候,采取措施进行恢复。
4.1每种类型一个资源的死锁检测
上图表示资源分配图,其中方框表示资源、圆圈表示进程。资源指向进程表示该资源已经分配给该进程,进程指向资源表示进程请求获取该资源。
图a可以抽取出环,如图b,它满足了环路等待条件,因此会发生死锁。
每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。
4.2每种类型多个资源的死锁检测
上图中,有三个进程四个资源,每个数据代表如下:
- E向量:资源总量
- A向量:资源剩余量
- C矩阵:每个资源所用的资源数量,每一行都代表一个进程有用资源的数量
- R矩阵:每个请求的资源数量
进程 P1 和 P2 所请求的资源都得不到满足,只有进程 P3 可以,让 P3 执行,之后释放 P3 拥有的资源,此时 A = (2 2 2 0)。P2 可以执行,执行后释放 P2 拥有的资源,A = (4 2 2 1) 。P1 也可以执行。所有进程都可以顺利执行,没有死锁。
算法总结如下:
每个进程最开始时都不被标记,执行过程有可能被标记。当算法结束时,任何没有被标记的进程都是死锁进程。
- 寻找一个没有标记的进程 Pi,它所请求的资源小于等于 A。
- 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。
- 如果没有这样一个进程,算法终止。
4.3死锁恢复
- 利用抢占恢复
- 利用回滚恢复
- 通过杀死进程恢复
六、死锁预防
6.1.破坏互斥条件
如果资源不被一个进程所独占,那么死锁肯定不会产生。当然,允许两个进程同时使用打印机会造成混乱,通过采用假脱机打印机(spooling printer)技术可以允许若干个进程同时产生输出。该模型中惟一真正请求使用物理打印机的进程是打印机守护进程,由于守护进程决不会请求别的资源,所以不会因打印机而产生死锁。
假设守护进程被设计为在所有输出进入假脱机之前就开始打印,那么如果一个输出进程在头一轮打印之后决定等待几个小时,打印机就可能空置。为了避免这种现象,一般将守护进程设计成在完整的输出文件就绪后才开始打印。例如,若两个进程分别占用了可用的假脱机磁盘空间的一半用于输出,而任何一个也没有能够完成输出,那么会怎样?在这种情形下,就会有两个进程,其中每一个都完成了部分的输出,但不是它们的全部输出,于是无法继续进行下去。没有一个进程能够完成,结果在磁盘上出现了死锁。
避免分配那些不是绝对必需的资源,尽量做到尽可能少的进程可以真正请求资源。
6.2.破坏占有和等待条件
只要禁止已持有资源的进程再等待其他资源便可以消除死锁。
实现一:规定所有进程在开始执行前请求所需的全部资源。如果所需的全部资源可用,那么就将它们分配给这个进程,于是该进程肯定能够运行结束。如果有一个或多个资源正被使用,那么就不进行分配,进程等待。
问题1:需要使用多少资源?如果进程能够知道它需要多少资源,就可以使用银行家算法。
问题2:这种方法分资源利用率不是最优。例如,有一个进程先从输入磁带上读取数据,进行一小时的分析,最后会写到输出磁带上,同时会在绘图仪上绘出。如果所有资源都必须提前请求,这个进程就会把输出磁带机和绘图仪控制住一小时。
解决问题后实现二:
要求当一个进程请求资源时,先暂时释放其当前占用的所有资源,然后再尝试一次获得所需的全部资源。将资源利用率达到最高
6.3.破坏不可抢占条件
假若一个进程已分配到一台打印机,且正在进行打印输出,如果由于它需要的绘图仪无法获得而强制性地把它占有的打印机抢占掉,会引起一片混乱。
但是,一些资源可以通过虚拟化的方式来避免发生这样的情况。假脱机打印机向磁盘输出,并且只允许打印机守护进程访问真正的物理打印机,这种方式可以消除涉及打印机的死锁,然而却可能带来由磁盘空间导致的死锁。但是对于大容量磁盘,要消耗完所有的磁盘空间一般是不可能的。
然而,并不是所有的资源都可以进行类似的虚拟化。例如,数据库中的记录或者操作系统中的表都必须被锁定,因此存在出现死锁的可能。
6.4.破坏环路等待
消除环路等待有几种方法:
- 保证进程在任何时刻只能占有一个资源,如果要请求另一个资源,他必须先释放第一个资源。但是假若进程正在把一个大文件从磁带上加载并发送到打印机上打印,这种方法是不可靠的。
- 另一种避免环路等待的的方法是给资源加上编号,进程可以在任何时刻提出资源申请,但是所有请求必须按照资源编号的顺序提出。进程可以先请求打印机再请求磁带机,但不可以先请求磁带机再请求打印机。
方法汇总
七、死锁避免
7.1安全状态
图a的**第二列Has表示已拥有的资源数,第三列Max表示总共需要的资源数,Free表示可以使用的资源数。**从a图开始出发,先让 B 拥有所需的所有资源(图 b),运行结束后释放 B,此时 Free 变为 5(图 c);接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。
定义:如果没有死锁发生,并且即使所有进程突然请求对资源的最大需求,也仍然存在某种调度次序能够使得每一个进程运行完毕,则称该状态是安全的。
安全状态的检测与死锁的检测类似,因为安全状态必须要求不能发生死锁。下面的银行家算法与死锁检测算法非常类似,可以结合着做参考比较。
7.2单个资源的银行家算法
小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是就拒绝请求,否则给与分配。
7.3多个资源的银行家算法
总结
内容出自:Andrew S.Tanenbaum教授写作的《现代操作系统原书》(第三版)