一组阻塞的进程持有一种资源等待获取另一个进程所占有的一个资源。
不 会 产 生 死 锁 不会产生死锁 不会产生死锁
会 产 生 死 锁 , 形 成 了 一 个 环 状 的 结 构 ( 一 个 大 环 和 小 环 ) 会产生死锁,形成了一个环状的结构(一个大环和小环) 会产生死锁,形成了一个环状的结构(一个大环和小环)
有 环 状 的 资 源 分 配 图 没 有 死 锁 , 如 P 2 释 放 , P 1 获 得 资 源 R 1 , 可 释 放 P 2 , P 3 获 得 R 2 执 行 有环状的资源分配图没有死锁,如P2释放,P1获得资源R1,可释放P2,P3获得R2执行 有环状的资源分配图没有死锁,如P2释放,P1获得资源R1,可释放P2,P3获得R2执行
产生死锁必须同时具备下面四个必要条件,只有其中一个条件不成立,死锁就不会发生。
死锁的处理可以分为下面这四种:
上述的四种方法,从(1)到(4)对死锁的防范程度逐渐减弱,但对资源利用率逐渐提高,以及进程因资源因素而阻塞的频率下降(即并发程度提高)
互斥条件是非共享设备必须的,不能改变,主要是破坏产生死锁的后三个条件。
为了破坏“请求和保持”条件,可以通过以下两个不同的协议实现:
第一种协议
该协议规定,所有进程在开始运行之前,必须一次性的申请其整个运行过的所需要的全部资源,该进程在整个运行期间,便不会再提出资源请求,从而破坏了“请求”条件。系统在分配资源时,只要有一种资源不能满足进程的要求,即使其它所需的各资源都空闲也不分配给该进程,而让该进程等待,则破坏了“保持条件”。
第一种协议简单,易行且安全,但缺点也比较明显:
(1)资源被验证浪费,严重恶化了资源的利用率
(2)使进程经常发生饥饿现象。可能个别资源长期被其他进程占用。
第二种协议
该协议是对第一种协议的改进,它允许一个进程只获得运行初期所需的资源后,便开始运行。进程运行过程中再逐步释放已分配给自己的、且已经用完的全部资源,再去请求新的所需资源。
第二种协议相比于第一种协议而言,提高的资源的利用率,也减少了进程发生饥饿的几率。
对系统所有资源类型进行线性排序,并赋予不同的序号。对系统所有资源进行线性排序,每个进程必须按照序号的地址顺序来请求资源。一个进程在开始时,可以请求资源 R 1 R_1 R1的单元,以后,当且仅当 F ( R j ) > F ( R i ) F(R_j) >F(R _i) F(Rj)>F(Ri),进程才可以请求资源 R j R_j Rj的单元。如果需要多个同类资源单元,则必须一起请求。
优点:
资源利用率和系统吞吐量都有比较明显的改善。
缺点:
- 系统中各类资源所规定的序号必须稳定,这就限制了新类型设备的增加
- 可能会发生作业使用各类资源的顺序与系统规定的顺序不同,造成资源的浪费。
- 为了方便用户,系统对用户在编程时所施加的限制条件应尽量少,然而这种按照规定次序申请资源的方法会限制用户简单,自主的编程
在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁,这种方法施加的限制条件较弱,可以获取较好的系统性能,目前常用此方法避免发生死锁。
把系统的状态分安全和不安全状态,安全状态可避免发生死锁,不安全状态可能进入到死锁状态。
避免死锁:确保系统进入不安全状态。
安全序列:是指系统能按某种进程推进顺序 ( P 1 , P 2 , . . . , P n ) (P_1, P_2, ... ,P_n) (P1,P2,...,Pn)为每个进程 P i P_i Pi分配其所需资源,对于每个 P i P_i Pi, P i P_i Pi仍然可以申请的资源数小于当前资源加上所有进程 P j P_j Pj ( j < i ) (j(j<i)所占用的资源,在这种情况下,进程 P i P_i Pi可以等待直到所有 P j P_j Pj释放资源。当他们完成时, P i P_i Pi可以得到所需的资源,完成给定的任务,返回分配的资源,最后终止。当 P i P_i Pi终止时, P i + 1 P_{i+1} Pi+1可得到需要的资源,如此进行。如果系统无法找到这样一个安全序列,则称系统处于不安全序列。
最具有代表性避免死锁的算法就是Dijkstra的银行家算法。
基本思想:在每个新进程进入系统时,他必须声明在运行过程中,可能需要的每种资源类型的最大单元数目(数目不超过系统拥有的资源总量)。当系统请求一组资源时,系统必须首先在确定是否有足够的资源分配给该进程。若有,在进一步计算将这些资源分配给进程后,是否会使系统处于不安全状态。如果不会,才将资源分配给他。
1.银行家算法的数据结构
为实现银行家算法,在系统中必须要有这样四个数据结构,分别用来描述系统中可利用的资源,所有进程对资源的最大需求,系统中的资源分配,以及所有进程还需要资源的情况。
可利用资源Available:这是一个含有m个元素的数组,其中每一个元素代表一类可利用的资源情况。其初始值是系统所配置的全部可用资源的数目。 如果Available[j] = k,则表示系统中现有 R j R_j Rj类资源K个。
最大需求矩阵Max: 这是一个 n ∗ m n*m n∗m的矩阵。它定义了系统中n个进程每一个对m类资源的最大需求。如果Max[i,j] = K,则表示进程i需要 R j R_j Rj类资源的最大数目为K。
分配矩阵Allocation:这也是一个n*m矩阵,它定义了系统中每一类资源当前已分配给每一类进程的资源。如果Allocation[i,j]= K ,则表示进程 i i i已分得 R j R_j Rj类资源的数目为K。
需求矩阵Need:这也是n*m的矩阵,用来表示每一个进程尚需的各类资源数,如果Need[i,j]=K,则表示进程i还需要K个 R j R_j Rj类资源才能完成任务。
三个矩阵关系:
N e e d [ i , j ] = M a x [ i , j ] − A l l o c a t i o n [ i , j ] Need[i,j]=Max[i,j]-Allocation[i,j] Need[i,j]=Max[i,j]−Allocation[i,j]
2.银行家算法
设 R e q u e s t i Request_i Requesti是 P i P_i Pi进程的请求向量,如果 R e q u e s t i [ j ] = K Request_i[j]=K Requesti[j]=K则表示 P i P_i Pi进程需要K个 R j R_j Rj 类资源。当 P i P_i Pi发出资源请求后,系统按照下述步骤进行检查
(1)如果 R e q u e s t i [ j ] < = N e e d [ i , j ] Request_i[j]<=Need[i,j] Requesti[j]<=Need[i,j],便转向步骤(2),否则认为错误,因为它所需要的资源数已超过它所宣布的最大值。
(2)如果 R e q u e s t i [ j ] < = A v a i l a b l e [ i , j ] Request_i[j]<=Available[i,j] Requesti[j]<=Available[i,j],便转向步骤(3),否则认为错误,表示尚无足够资源, P i P_i Pi等待。
(3)系统试探把资源分配给进程 P i P_i Pi,并修改下面数据结构的值:
A v a i l a b l e p [ j ] = A v a i l a b l e [ j ] − R e q u e s t i [ j ] Availablep[j]=Available[j]−Requesti[j] Availablep[j]=Available[j]−Requesti[j]
A l l o c a t i o n [ i , j ] = A l l o c a i o n [ i , j ] + R e q u e s t i [ j ] Allocation[i,j]=Allocaion[i,j]+Requesti[j] Allocation[i,j]=Allocaion[i,j]+Requesti[j]
N e e d [ i , j ] = N e e d [ i , j ] − R e q u e s t i [ j ] Need[i,j]=Need[i,j]−Requesti[j] Need[i,j]=Need[i,j]−Requesti[j]
(4)系统执行安全性算法,检查此次分配是否处于安全状态,若属于安全状态,则将资源正式分配给进程 P i P_i Pi,以完成本次分配。否则将本次试探分配作废,恢复原来的资源分配状态,让进程 P i P_i Pi等待。
3.安全性算法
系统所描述的安全性算法可以描述为下:
数据结构
(1)设置两个变量:
(2)从进程集合中找到一个满足下述条件的进程:
Finish[i] = true;
Need[i,j]<=Work.
若找到执行步骤(3),否则执行步骤(4);
(3)当进程 P i P_i Pi获得资源后,可顺利执行,直到完成,并释放它的资源。故应执行:
Work[j] = Work[j] - Allocation[i,j];
Finish[j] =true;
go to step 2;
(4)如果所有进程的Finish[i] = true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。
eg1
p 2 可 以 满 足 情 况 , 执 行 后 可 返 回 其 所 占 有 的 资 源 p2可以满足情况,执行后可返回其所占有的资源 p2可以满足情况,执行后可返回其所占有的资源
回 收 资 源 之 后 , 按 照 顺 序 , p 1 所 需 要 的 资 源 是 可 以 满 足 的 , 可 以 执 行 回收资源之后,按照顺序,p1所需要的资源是可以满足的,可以执行 回收资源之后,按照顺序,p1所需要的资源是可以满足的,可以执行
p 1 执 行 后 , 对 资 源 进 行 回 收 , 剩 下 的 两 个 进 程 可 以 满 足 要 求 , 随 便 选 一 个 , 比 如 p 3 , 然 后 再 选 择 p 4 p1执行后,对资源进行回收,剩下的两个进程可以满足要求,随便选一个,比如p3,然后再选择p4 p1执行后,对资源进行回收,剩下的两个进程可以满足要求,随便选一个,比如p3,然后再选择p4
这样就已经找到了一个序列,如果按照p2-p1-p3-p4这个顺序去执行,就可以实现所以的进程都可以正常的执行并结束,其所需要的资源都可以得到满足。这个就是安全的执行序列。
eg2:
如 果 一 开 始 p 1 提 出 了 一 个 101 请 求 , 执 行 之 后 如果一开始p1提出了一个101请求,执行之后 如果一开始p1提出了一个101请求,执行之后
此时系统所剩余的资源为011,此时不能满足任何的其他进程,会进入一个unsafe的状态。所以,一开始银行家算法是不会接受p1的101的请求的。
总结:
银行家算法的思路是判断当前的资源分配操作是否安全的,如果安全则可以执行,如果不安全就不能分配出去。
1.背景
死锁的检测又将条件放宽了一点。
2.死锁检测的大致思路
3.检测原理
死锁检测中的数据结构类似于银行家算法中的数据结构:
将资源分配图中资源的节点简化,只留下进程。从而将资源分配图,变成进程等待图。然后再判断这个等待图是否具有环。有环就代表有可能死锁。
死锁检测算法,定期的执行对操作系统运行比较大,更多是起调试的作用。而已银行家算法需要提前知道进程未来所需要的资源,这个是比较难实现的,只能去预估。