死锁的原理:
- 一组进程中每个进程都无限等待被该组进程中另一进程所占有的资源,而处于的一种僵持局面,若无外力作用,它们都无法向前推进, 这种现象称为进程死锁(Deadlock),这组进程就称为死锁进程。
死锁产生的原因
1.竞争资源引起进程死锁
- 可剥夺和非可剥夺资源 (抢占)
①可剥夺资源:进程在获得这个资源后可以在被其它进程或系统剥夺
②非可剥夺资源:资源被系统分配给某个进程后就不能强行收回,只能进程自己释放 - 竞争非可剥夺资源
竞争临时性资源(进程通信时)
2.进程推进顺序不当引起死锁
3.死锁产生的必要条件
- 互斥条件:涉及的资源是非共享的
- 不可抢占条件:不能剥夺进程拥有资源
- 占有和等待条件:进程在等待一新资源时继续占有已分配的资源
- 环路等待条件:存在一种进程的循环链,链中的每一个进程已获得的资源同时被链中的下一个进程所请求
4.死锁的处理方法
1.预防死锁
通过设置某些限制条件,去破坏死锁四个必要条件中的一个或多个,来防止死锁。
破坏互斥
**互斥条件不可破坏。因为一旦互斥条件破坏,就不存在多道程序设计了。**
破坏占有且等待
资源静态分配法:程序运行前,**一次性分配所有需要的资源。**若有某个资源不能满足,则全部不分配。进程等待直至所有资源可用。
问题:
- 可能会引起进程饥饿;资源利用率低。
- 进程可能事先不知道所需要的资源列表。
破坏不可抢占
进程申请新资源被阻塞时,必须(主动)释放已占有的资源。本进程需要时再重新申请。
OS剥夺低优先级进程的资源给高优先级进程。
破坏循环等待
①资源有序分配法:系统内每个资源一个编号,各进程必须严格按照编号递增的顺序申请资源。
特点:
- 较易实现,广泛使用。
- 由于所施加的限制往往太严格,可能导致系统资源利用率和系统吞吐量的降低。
2.避免死锁(deadlock avoidance)
不事先采取限制去破坏产生死锁的条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免死锁的发生。
两种死锁避免方法:
- ①进程启动拒绝:如果一个新进程的资源最大需求总量会导致死锁,则不启动此新进程。
- ②资源分配拒绝:如果一个进程提出的某次资源请求会导致死锁,则不允许此次分配。(更常用)
2.1进程启动拒绝
定义以下向量和矩阵:n——进程数;m——资源类型数
- 资源总量Resource = R = (R1, R2,…,Rm)
- 可用资源Available = V = (V1,V2,…,Vm)
- 最大需求矩阵Claim = C = :n*m 的矩阵 ——C[i,j] = k 表示进程 i 需要第 j 类资源最多为k个。
- 已分配矩阵Allocation = A = n*m的矩阵 ——A[i,j] = k 表示进程 i 已分得第 j 类资源 k 个。
当系统的资源总量能够满足“所有进程的最大需求量加上新进程Pn+1的最大需求量”时,才能启动新进程Pn+1。
(即所有进程申请的资源最大需求量之和不能大于系统的资源总量。)
2.2 资源分配拒绝(银行家算法)
-
银行家算法:分配资源前,先计算此次分配是否会导致系统处于不安全状态。若安全则分配,否则不分配(事先评估)。
- 安全状态:存在一个由所有进程(P1,P2,…,Pn)构成的安全序列,如果系统安照这个顺序为每个进程分配所需资源,直至该进程声明的最大资源需求量,则可以使每个进程都运行完。
- 不安全状态:系统不存在任何一个安全序列,使得所有进程都能够运行完。
进程提出资源分配请求后,OS先试探性分配,若仍处于“安全状态”才分配,否则暂不分配,进程等待。
- 安全性测试算法(银行家算法)
boolean safe(state S){
int currentavail[m];//系统可用资源数目(临时记录,非真实)
process rest[进程总数];//剩余的,未运行完毕的进程集合
currentavail = available;//开始时,currentavail = 实际的可用资源
rest = {所有进场};//开始时,所有进程都尚未运行完毕
possible = true;
while(possible){
<在rest中(循环)查找一个进程Pk,满足claim[k,*]-alloc[k,*]<= currentavail;>
//其资源需求可被满足
if(found){//如果有这样的进程Pk,则认为它能够运行完毕
currentavail = currentavail+alloc[k,*];//并释放其已分配的资源
rest=rest-{Pk};//从rest集合中去掉“已运行完的”进程Pk
}
else possible = false;//如果没有找到这样的进程Pk,则结束循环
}
return (rest == null);//若rest为空,则为安全状态,否则不安全
}
特点:
- 事先只需要较弱的限制条件,可获得较高的资源利用率和系统吞吐量。
- 实现较难。
3.检测死锁(deadlock detection)
- 事先并不采取任何限制,也不检查系统是否进入不 安全区,允许死锁发生;
- 但可通过检测机构及时检测出死锁的发生,并精确确定与死锁有关的进程和资源,然后采取适当措 施,将系统中已发生的死锁清除掉。
- 只要所请求资源可用,则分配给进程。OS定期运行死锁检测算法,判断是否存在死锁。
死锁检测算法类似于银行家算法。
4.解除死锁(deadlock recovery)
4.1恢复
解除死锁:代价最小地撤销进程、剥夺资源。
* 终止所有死锁进程。
* 每个死锁进程回滚到某个安全状态的“检查点”(周期性将内存映像、资源状态等写入文件),并重启进程。
* 每次终止一个死锁进程,直到死锁环解除。
* 每次剥夺一个资源,直至死锁环解除。
选择终止进程顺序和剥夺自愿的顺序
* 进程已运行时间最少,预计剩余运行时间最长。
* 进程已产生的输出最少,已用资源总量最少。
* 进程的优先级最低,进程是交互式的还是批处理的。
* 防止饥饿:避免总是选择同一个牺牲者(考虑其回滚的次数)。
- 与检测死锁相配套,用于将进程从死锁状态解脱出来。
- 常用的方法是撤消或挂起一些进程。以回收一些资源,再将它们分配给处于阻塞状态的进程,使之转为就绪状态。
- 实现难度大,但可获得较好的资源利用率和系统吞吐量。