重要点用这个颜色标出
死锁:某个进程申请资源,如果这时资源不可用,那么该进程进入等待状态;如果所申请的资源被其他等待进程占有,那么该等待进程有可能再也无法改变其状态。
——多个进程竞争性使用资源,产生了一个永久性阻塞状态
-例子:交叉路口问题:图
如果一个车退一步就可以解决死锁,但是这辆车可能再也不能前进了(其他进程一直抢占资源)
可能出现饥饿问题;但大多数操作系统都没有解决死锁的机制。
题目类型(下去搜一下经典题目,考研题):用现实生活中例子来分析,如哲学家就餐,银行家,车辆,
一、系统模型
假设资源类型为R1,R2...Rm (如CPU区间、内存空间、IO设备),每种资源的数量有w个(每种资源有w个实例)
在正常操作下,进程使用资源需要按照如下顺序:
申请request(wait())、使用use(CS)、释放release(signal());
二、死锁特征和解决
(1)死锁产生的必要条件:四个条件同时满足才能产生死锁
1. 互斥mutual exclusion:至少要一个资源是非共享的(互斥的)。一次只能由一个进程使用,如果另一个进程申请资源,那么申请进程必须等待,直到该资源被释放。
2. 占有并等待hold and wait:一个进程必须至少占有一个资源,并等待其他资源,而等待的这些资源被其他进程占有。
3. 非抢占no preemption:进程所获得资源在未使用完毕之前,不能被强行夺走,只能由进程完成任务后自己自动释放。
4. 循环等待Circular wait:存在一个循环链,链中每一个进程已获得的资源同时被链中下一个进程所请求。
具体来说:有一组等待进程{P0,P1,P2,P3…,Pn},P0等待的资源被P1等待,P1等待的资源被P2所占有,……,Pn−1等待的资源为Pn所占有,Pn所等待的资源被P0所占有。
(2)资源分配图
死锁问题可用称为系统资源分配图的有向图进行更为精确地描述,这种图由一个节点集合V和一个边集合E组成。
节点集合V可以分成两种类型的节点:
P={P1,P2,…,Pn}(系统活动进程的集合)
R={R1,R2,…,Rn}(系统所有资源的集合)
申请边:Pi→Rj 表示进程Pi已经申请了资源类型为Rj的一个实例
分配边:Rj→Pi 表示资源类型Rj已经分配给进程Pi
这个有向图无环,所以一定没有死锁。
分配图与死锁关系:
如果分配图没有环,那么系统就没有进程死锁。如果分配图有环,那么可能存在死锁;
如果每个类型只有一个实例,环是死锁存在的充分必要条件。如果每个类型不止一个实例,存在环不一定死锁,此时环是死锁的必要条件。
具体例子分析:
左图有死锁,右图无死锁(因为P2和P4可以运行结束后释放资源)
(3)死锁处理方法
三种思路:
死锁预防、死锁避免、死锁检测并恢复、忽略
1.可使用协议以预防或避免死锁,确保系统不会进入死锁状态。
死锁预防(deadlock prevention):确保死锁的四个必要条件至少有一个不成立。通过限制资源申请的方法来预防死锁。死锁预防比死锁避免更严格;
死锁避免(deadlock avoidance):允许三个必要条件成立,但是通过其他方法保证第四个条件一定不成立——让死锁条件不完全成立。
2.deadlock detection可允许系统进入死锁状态,然后检测它,并加以修复。
3. (鸵鸟策略)忽略这个问题,认为死锁不可能在系统内发生。(为绝大多数操作系统所用,因为实际死锁出现概率小,因此应用程序开发人员需要自己来处理死锁)
(4)死锁预防prevention
确保死锁的四个必要条件至少有一个不成立,即让其中一个条件永远不发生即可,下面通过分别讨论四个必要条件来研究死锁预防:
1.互斥:非共享资源必须有互斥条件,不然会导致信息不一致性。所以通常互斥不能避免;而不需要互斥的共享资源一定不会导致死锁。
2.占有并等待:要这个条件不成立,即当一个进程申请一个资源时,不能占有其他资源。
a.可以让每个进程在执行前申请获得所有资源,
b.进程在没有资源时才可以申请资源,如果已经有了资源还要申请其他资源,就必须先释放目前拥有的所有资源。
缺点:资源利用率低,一起分配资源可能导致一些资源分配了但是很长时间没有使用,比如分配了IO和文件,但是只在最后才需要IO写入文件,之前一直在CPU计算;
可能发生饥饿,因为一个进程如果需要多个常用资源,则可能产生永久等待。
3.非抢占:要这个条件不成立,即允许抢占。如果一个进程处于等待状态,其他进程申请其拥有的资源,则可以抢占它的资源;
一般用于可保存和恢复状态的资源,如CPU资源和内存。其他资源,可能会出现同步问题
4.循环等待:对所有na资源进行编号,完全排序,要求每个进程按照递增顺序来申请资源(先获得低优先级资源才能获得高优先级资源)。
缺点:资源利用率低,系统吞吐率低
(5)死锁避免avoidance
死锁避免算法动态地检测资源分配状态以确保循环等待条件不可能成立,
资源分配时考虑该分配是否会导致不安全状态,如果会导致则不分配资源。
资源分配状态:可用资源available、已分配资源allocation、进程最大需求Need
缺点:设备利用率低,系统吞吐率低
需要操作系统事先得到有关进程未来申请资源和使用资源的额外信息(完全顺序),来判断当前资源分配是否安全。(比如知道拿起笔之后要写字,知道了每个进程申请释放的完全顺序,就可以决定是否安全,是否分配资源)
安全状态:存在一个安全序列即处于安全状态
安全序列:进程顺序{P1,P2,…,Pn},如果对于每个Pi,Pi仍然可以申请的资源数(还需要的资源数)小于当前可用资源加上所有进程Pj(j小于i)所占用资源,那么这一顺序称为安全序列。本质是进程可以安全运行不产生死锁的顺序。
翻译一下就是:系统能按某个顺序为每个进程分配资源(不超过其最大值)并能避免死锁;Pi前的进程完成后可以释放出来它们之前占有的资源,所以Pi前的进程完成后给出的资源和目前空闲的资源加起来 比 Pi还需要申请的资源大的话,就是安全的,也就是说这一序列的进程可以顺利完成。
安全状态和死锁的关系:安全与不安全是互不相容的,不安全状态包括了死锁。
(6)死锁避免算法:
- 每种资源只有单个实例——资源分配图算法
- 资源有多个实例——银行家算法(安全性算法、资源请求算法)
资源分配图算法:
需求边Pi→Rj表示进程Pi可能在将来某个时候申请资源Rj。只有需求边变为分配边而不会导致资源分配图形成环时,才允许申请。(如果有环存在则分配会导致系统处于不安全状态)
需求边——虚线的申请边
例子:
假如进程P2申请资源R2。虽然R2现在可用,但是不能分配给P2,因为这会创建一个环,环表示系统处于不安全状态,如果P1再申请R2就会造成死锁。
银行家算法
对于每种资源类型有多个实例的资源分配系统,资源分配图就不再适用,需要使用银行家算法,但是效率比资源分配图算法低。
当新进程进入系统时,它必须说明其可能需要的各种类型资源实例的最大数量,这一数量不能超过当前系统资源的总和。
当用户申请一组资源时,系统必须确定这些资源的分配是否仍会使系统出于安全状态,如果是,就分配资源;否则,进程必须等待直到某个其他进程释放足够资源为止。
必要的四个数据结构:Available,Max,Allocation,Need
记录资源分配状态,这些数据结构的大小和值会随着时间而改变
设n为系统的进程的个数,m为资源类型的种类:
Available:长度为m的向量,表示每种资源类型的现有实例的数量。
Available[j] = k,说明资源类型Rj有k个实例。
Max:n×m矩阵,定义每个进程对某类资源的最大需求(总需求)
Max[i][j] = k,进程Pi最多申请k个资源类型Rj的实例。
Allocation:n×m矩阵,定义每个进程现在所分配的各种资源类型的实例数量(已经得到的资源实例数)
Allocation[i][j]= k,进程Pi现在已经分配了k个资源类型为Rj的实例。
Need:n×m矩阵,表示每个进程还需要的资源。
Need[i][j] = k,进程Pi还需要申请k个资源类型为Rj的实例。Need[i][j] = Max[i][j] - Allocation[i][j]
为了简化银行家算法的描述:
设X,Y为长度为n的向量,X≤Y当且仅当对所有的i=1,2,…,n,X[i]≤Y[i];如果X≤Y且X!=Y,那么X<Y。
将矩阵Allocation 和Need的每行作为向量,并分别用Allocationi 和Needi来表示。向量Allocationi表示分配给进程Pi的资源,Needi表示进程Pi为完成其任务可能仍需要申请的资源。
(1)安全性算法
确定计算机是否处于安全状态,具体步骤如下:
(n为系统的进程的个数,m为资源类型的种类)
1.创建Work和Finish向量,长度分别为m,n,并且Work=Avallable,将Finish的每一项置为false;
2.查找是否存在这样的i满足:
Finish[i]=false
Needi<=Work
如果不存在则跳到第四步;
(满足上述两个条件表示这个进程Pi在目前空闲的资源下是可以运行的)
3.如果存在上述Pi,则Pi可以运行,运行结束后可以释放占有资源:
Work=Work+Allocationi
Finish[i]=true
跳回第二步;
4.如果对所有的i,Finish[i]=true(所有进程均可顺利运行结束),那么系统处于安全状态。
注:如果剩余资源可满足任意资源结束,则可以任意选择
(2)资源请求算法
判断是否可以安全允许请求的算法:
设Requesti为进程Pi的请求向量:
(长度为资源类型数m,Requesti[j]==k,表示Pi所需要资源类型Rj的实例数量为k)
当进程Pi做出资源申请时,采取如下步骤:
1.如果Requesti<Needi,那么进行下一步;否则产生出错条件,因为请求的资源已经超过了其剩余需要的资源。
2.如果Requesti<Available,那么进行下一步;否则Pi必须等待,因为可用的资源不足以满足这个请求。
3.假定系统可以分配给进程Pi所需的资源,按如下方式修改状态:
Available=Available−Requesti
Allocationi=Allocationi+Requesti
Needi=Needi−Requesti
判断目前的状态是否安全(用安全性算法),如果进行了上述修改所产生的资源分配状态是安全的,那么分配完成;
如果新状态不安全,那么进程Pi必须等待Requesti并恢复到最开始的资源分配状态(回退
三、死锁检测detection
每种资源类型只有单个实例:
等待图wait-for图(资源分配图的变种)
从资源分配图中,删除所有资源类型节点,合并适当边,就可以得到等待图。等待图中由Pi到Pj的边意味着进程Pi等待进程Pj释放一个Pi所需的资源(即对应资源分配图中包含Pi->Rq,Rq->Pj的边)
系统中存在死锁当且仅当等待图中有环。为了检测死锁,系统需要维护等待图,并周期性调用在图中进行搜索的算法。从图中检测环的算法需要n2级别操作,其中n为图中的节点数(进程数量)。
多个实例——和银行家算法类似,不同的地方加上了下划线
Available:长度为m的向量,表示每种资源类型的现有实例的数量。
Available[j] = k,说明资源类型Rj有k个实例。
Allocation:n×m矩阵,定义每个进程现在所分配的各种资源类型的实例数量(已经得到的资源实例数)
Allocation[i][j]= k,进程Pi现在已经分配了k个资源类型为Rj的实例。
Request:n×m矩阵,表示每个进程当前的资源请求情况
Need[i][j] = k,进程Pi正在请求k个资源Rj
1.创建Work 和 Finish 向量,长度分别为m,n。初始化Work=Available。
如果Allocationi不为0,初始化Finish[i]=false, 如果Allocationi为0,初始化Finish[i]=true;(不占有资源的不考虑)
2.查找是否存在i满足:
Finish[i]=false
Requesti<=Work
如果不存在则跳到第四步。
3.
Work= Work + Allocationi
Finish[i] = true
跳回第二步
4.如果对某个i存在Finish[i] == false,进程Pi死锁,系统处于死锁状态。
分析:
Requesti<=Work之后可以回收进程Pi的资源是因为可以乐观的假设Pi不再需要更多的资源就可以完成任务,然后返回目前占有的所有资源;如果这个假设不正确,下一次再调用死锁检测算法进行死锁检测时会检测到死锁。
应用检测算法
何时应用检测算法取决于两个因素:死锁可能发生的频率和死锁发生时影响的进程数量。
检测算法一般不会频繁运行,因为对每个请求都调用死锁检测算法开销大:极端情况下,在每次请求分配不能立即允许时,就调用死锁检测算法;(因为只有请求得不到满足才可能出现死锁)
或者以一个不太高的频率调用检测算法,如每小时一次,或者CPU利用率低于40%时调用(死锁会导致系统性能下降,导致CPU利用率下降);但这样通常不能确定死锁进程中哪些“造成”了死锁。
四、死锁恢复
死锁已经发生要如何处理:
人工处理/系统处理:一种措施是通知操作员死锁已发生,以便操作人员人工处理死锁;另一种措施是让系统从死锁状态中自动恢复过来。
打破死锁有两种处理方法:
1.(进程终止)简单地终止或多个进程以打破循环等待。
两种具体方法:(两种方法代价都很大,各有优缺点)
(1)终止所有死锁进程,计算结果被抛弃;
(2)一次只终止一个进程直到没有死锁循环为止,每次都需要调用死锁检测算法检测是否处于死锁。
存在的问题:
应该终止代价最小的进程——如何确定代价最小?需要考虑多种因素,包括(进程优先级、已计算时间、完成还需时间、使用的资源类型和数量、需要终止进程的数目、进程类型是批处理还是交互的)
2.(资源抢占)从一个或多个死锁进程那里抢占一个或多个资源。
存在三个问题:
①选择一个牺牲品:抢占哪些资源和哪个进程?
必须确定抢占顺序以使代价最小化。
②回滚:如何回滚?
必须将这个进程回滚到某个安全状态,以便以后重启进程。最简单的方法是完全回滚:终止进程并重新执行;更为有效的方法是将进程回滚到足够打破死锁。另一方面,这种方法要求系统维护有关运行进程状态的更多信息。
③饥饿:如何确保不会发生饥饿?
有的低优先级进程总是被选为牺牲品,导致饥饿;最为常用的解决方法是在代价因素中加上回滚次数。
本章题目:
1.给定资源分配状态判断是否有死锁
2.银行家算法具体应用:
假定系统中有4个进程P1、P2、P3、P4和3种类型的资源R1、R2、R3,数量分别为9、3、6,在t0时刻的资源分配情况如表所示。
t0时刻的资源分配表:
试问:
(1)t0时刻是否安全?
(2)P2发出请求向量Request2(1,0,1),系统能否将资源分配给它?
(3)在P2申请资源后,若P1发出请求向量Request1(1,0,1),系统能否将资源分配给它?
(4)在P1申请资源后,若P3发出请求向量Request3(0,0,1),系统能否将资源分配给它?
解答:
(1)安全序列:P2、P1、P3、P4(后面三个顺序随机)
(2)可以分配,因为分配资源后可找到一安全序列:P2、P1、P3、P4
(3)不能分配,因为request1(1,0,1)>available(0,1,1)
(4)不能分配,因为分配资源后找不到一安全序列。