操作系统中死锁的定义产生原因必要条件死锁的处理策略死锁预防和避免死锁的检测和解除
操作系统中死锁的定义、产生原因、必要条件、死锁的处理策略(死锁预防和避免、死锁的检测和解除)
死锁定义
- 死锁(deadlock) :如果一组进程中每个进程都在等待一个事件,而这个事件只有该集合中的另一个进程才能引起,那么该集合就是死锁的。(都占有资源,然后互相等待)
- 或者两个或以上的进程因为争夺资源而造成互相等待的现象,并且若无外力作用,它们都将无法继续推进下去
死锁产生的原因
- 系统资源不足
- 进程运行时推进测顺序不合适
- 资源分配不当
死锁产生的四个必要条件
- 互斥条件 :进程对分配到的资源进行排他使用,即在一段时间内某资源只能被一个进程占用,其他请求该资源的进程进行等待,直到该资源释放。
- 请求和保持条件 :一个进程因为请求资源而阻塞等待时,对自己已经获得的资源保持不放。
- 不可抢占(剥夺)条件 :进程已经获得的资源,在未使用完之前不能被强行剥夺。
- 循环等待条件 :若干进程之间形成一种环形的等待资源关系。
死锁的处理策略
- 采用某个协议类预防或避免死锁,确保系统永远不会进入死锁状态。
- 允许系统进入死锁状态,但是会检测它,然后解除。
- 完全忽略这个问题,并假设系统永远不会出现死锁
第一种策略死锁预防和避免
死锁预防
破坏请求保持条件
OS要做到:当一个进程在请求资源时,不能持有不可抢占资源。通过以下两个协议来实现:
第一种协议 :所有进程在开始运行之前,必须 一次性 地 申请 在其整个运行工程中所需的 全部资源 。
若系统有足够分配的资源,则把其需要的所有资源分配给它,但只要有一种资源不能满足进程的要求,其它所需资源不会分配,该进程等待。
优点: 简答、易行、安全。
缺点: ①资源严重浪费,严重降低资源的利用率。某些资源可能只是在运行初期或快结束时使用 ②进程经常会发生饥饿现象。个别资源长期被其它进程占用,等待该资源的进程迟迟不能运行。
第二种协议: 允许一个进程 只获得 运行初期的所需的资源后便开始运行,在运行过程中逐步释放已分配给自己(已经使用完毕)的资源,然后再申请新的所需资源。
优点: 更快的完成任务、提高资源利用率、降低进程饥饿的概率
破坏不可抢占(剥夺)条件
当一个进程已经保持了某些不可抢占的资源时而新的资源请求不能得到满足,它必须释放已经保持的所有资源,待以后需要时重新申请。
**缺点:**实现复杂、可能使前一阶段的工作实效、延迟进程的周转时间、增加系统开销、降低系统吞吐量。
破坏循环等待条件
对系统的所有资源进行线性排序,赋予不同的序号,规定每个进程必须按照序号递增的顺序请求资源。
缺点: ①限制了新设备的增加。②作业使用资源的顺序和系统规定顺序不同,造成资源浪费。③用户编程实现麻烦。
死锁避免
系统安全状态
安全状态: 系统按某种推进顺序(P1,P2,…Pn),为每个进程Pi分配其所需的资源,直到满足每个进程的最大需求,进而使每个进程都可顺利完成的一种系统状态。
此时称 推进顺序(P1,P2,…Pn) 为 安全序列 。如果系统无法找到这样一个安全序列,则称系统处于不安全状态。
只要系统处于安全状态就不会进入死锁,而不安全状态可能会进入死锁,进入死锁的一定是系统处于不安去状态。
例如在 t 时刻有以下进程资源分配表
进程 | 最大需求 | 已分配 | 可用 |
---|---|---|---|
P1 | 10 | 5 | 3 |
P2 | 4 | 2 | 3 |
P3 | 9 | 2 | 3 |
则称 t 时刻系统是安全的,因为存在按照安全序列(P2,P1,P3)分配资源,可使每个进程顺利完成。
银行家算法
每个进程在运行前先声明对各种资源的最大需求数,不应超过系统所拥有的的资源总量。当进程申请资源时会先判断是否有足够的资源来满足该进程,
若有,则进一步计算分配资源后,系统是否会处于不安去状态,若是则让线程等待。
银行家算法数据结构
(1) 可利用资源向量Available,一个长度为m的一维数组表示当前系统中还有多少可用资源。
(2) 最大需求矩阵Max,可用一个n *m的矩阵(可用二维数组实现)表示所有进程对各种资源的最大需求数。
(3)分配矩阵Allocation,可以用一个n* m的分配矩阵Allocation表示对所有进程的资源分配情况。
(4)需求矩阵 Need,n*m的矩阵实现,表示各进程最多还需要多少各类资源。
Need[i,j] = Max[i,j] - Alloction[i,j]
银行家算法步骤:
①检查此次申请是否超过了之前声明的最大需求数。
②检查此时系统剩余的可用资源是否还能满足这次请求。
③试探着分配,更改各数据结构。
④用安全性算法检查此次分配是否会导致系统进入不安全状态
按一下步骤进行检查:
①如果Request[i,j] <= Need[i,j]0 ≤ j ≤ m)便转向②;否则认为出错。
②如果Request[i,j] ≤ Available[i,j] (o <= j <= m),便转向③﹔否则表示尚无足够资源,Pi必须等待。
③系统试探着把资源分配给进程Pi,并修改相应的数据(并非真的分配,修改数值只是为了做预判):
Available[j] = Available[j] - Request[j];
Allocation[i, j] = Allocation[i, j] + Request[j];
Need[i, j] = Need[i, j] - Request,[j]
④操作系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式分配;否则,恢复相应数据,让进程阻塞等待。
第二种策略死锁检测和解除
死锁检测
通过简化资源分配图来检测系统所处的某状态
如果系统中剩余的可用资源数足够满足进程的需求,那么这个进程暂时是不会阻塞的,可以顺利地执行下去。如果这个进程执行结束了把资源归还系统,就可能使某些正在等待资源的进程被激活,并顺利地执行下去。相应的,这些被激活的进程执行完了之后又会归还一些资源,这样可能又会激活另外一些阻塞的进程…
如果按上述过程分析,最终能 消除所有边 ,就称这个图是 可完全简化 的。此时一定 没有发生死锁 (相当于能找到一个安全序列)
补充:并不是系统中所有的进程都是死锁状态,用死锁检测算法 化简 资源分配图 后 ,还 连着边 的那些 进程 就是死锁进程
死锁解除
解除死锁的主要方法有:
1.抢占资源 :从一个或多个进程中抢占足够数量的资源,然后将他们分配给死锁进程,解除死锁状态。
2.终止进程法 :强制撤销部分、甚至全部死锁进程,并剥夺这些进程的资源。这种方式的优点是实现简单,但所付出的代价可能会很大。因为有些进程可能已经运行了很长时间,已经接近结束了,一旦被终止可谓功亏一篑,以后还得从头再来。