操作系统之死锁

死锁

前言

​ 大部分的死锁都和资源相关,所以首先要关注资源是什么。在进程对设备、文件等取得了排他性访问权时,就可能会出现死锁。把这类排他性使用的对象称为资源,资源可以是硬件设备或是一组信息。简单来说,资源就是随着时间的推移,必须能获得、使用以及释放的任何东西!!

可抢占资源和不可抢占资源

可抢占资源可以从拥有它的进程中抢占而不会产生任何副作用,存储器就是一类可抢占资源。

不可抢占资源是指在不引起相关的计算失败的情况下 ,无法把它从占用它的进程中抢占过来。

什么是死锁

​ 指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵局状态时,如果没有外力的推动,那么这多个进程将无法前进。如下图所示:

在这里插入图片描述

​ 具体一点的例子,如下代码。假设现存在进程A与进程B,这两个进程都会访问资源a、资源b。进程A访问资源的顺序是先访问资源a,然后在访问资源b;进程B访问资源的顺序是先访问资源b,然后再访问资源a;假如现在进程A给资源a加锁了,并且请求访问b资源,但是进程B给资源b加锁,同时也请求访问a资源。那么这两个进程就陷入了僵持状态,相互等待资源。

seamphore a,b;

void funcA(){
	while(1){
		// 占有锁a 进入临界区
		P(a);
		/*进行操作*/
		// 试图占有锁b
		P(b);
		V(b);
		
		// 释放锁a
		V(a);
	}
}

void funcB(){
	while(1){
		// 占有锁b 进入临界区
		P(b);
		/*进行操作*/
		// 试图占有锁a
		P(a);
		V(a);
		
		// 释放锁a
		V(b);
	}
}

产生死锁的原因

  1. 系统资源的竞争

    ​ 在系统所配置的非剥夺性资源,由于它们的数量不能满足进程运行的需要,会使进程在运行过程中,因为争夺这些资源而进入僵局。

    ​ 例如,系统中只有一台打印机R1和一台磁带机R2,可供进程P1和P2共享。假定P1占用了R1,P2占用了R2 。此时,若P2继续要求打印机,P2将阻塞;P1要求磁带机,P1也会阻塞。于是,P1和P2之间形成了僵局。两个进程都在等待对方释放出自己所需的资源!!!如下图所示:

    在这里插入图片描述

  2. 进程推进顺序非法

    在这里插入图片描述

    如曲线4所示,该进程不能进入临界区D中,因为P1锁了R1,P2锁了R2,同时P1请求R2,P2请求R1导致两个进程相互竞争资源,发生死锁的情况 !!!

  3. 信号量使用不得当

    ​ 进程间彼此相互等待对方发来的消息,结果也会使得这 些进程间无法继续向前推进。例如,进程A等待进程B发的消息,进程B又在等待进程A 发的消息,可以看出进程A和B不是因为竞争同一资源,而是在等待对方的资源导致死锁。

  4. 死锁产生的必要条件——死锁发生时,以下四个条件一定是同时满足的!!

    • 互斥条件。每个资源要么已经分配给了一个进程,要么就是可用的。若已分配其他请求的进程必须等待。
    • 占有和等待条件。已经得到了某个资源的进程可以再请求新的资源
    • 不可抢占条件。已经分配给一个进程的资源不能强制性地被抢占,只能显示地被释放
    • 环路等待条件。死锁发生时,系统中一定有由两个或两个以上的进程组成的一条环路,该环路的每个进程都在等待着下一个进程所占有的资源。

死锁预防

​ 由上面可知,死锁的出现必须要满足四个条件。那么如过破环其中一个条件,那么死锁将不会产生。

  1. 破坏互斥条件

    ​ 就是在系统里取消互斥。若资源不被一个进程独占使用,那么死锁是肯定不会发生的。但一般来说在所列的四个条件中,“互斥”条件是无法破坏的,因为不同的进程同时访问一个资源可能会产生异常。因此,在死锁预防里主要是破坏其他几个必要条件,而不去涉及破坏“互斥”条件。

  2. 破坏占有并等待条件

    只要禁止已持有资源的进程再等待其他资源便可以消除死锁。存在两种解决方案:

    • 规定所有进程再开始执行前请求所有资源,如果所有资源可用,那么就可以分配到这个进程中,进程肯定能运行结束。如果有一个或多个资源正被使用,那么就不进行分配,进程等待。但是!很多进程都是直到运行时才知道它需要多少资源,如果能知道需要多少资源也就能使用银行家算法。其次,这种方法的资源利用率非常低!
    • 要求当一个进程请求另一个资源时,必须释放当前占有的所有资源,然后再尝试以此获得所需的全部资源
  3. 破坏不可抢占条件

    破坏“不可抢占”条件就是允许对资源实行抢夺

    • 如果占有某些资源的一个进程进行进一步资源请求被拒绝,则该进程必须释放它最初占有的资源,如果有必要,可再次请求这些资源和另外的资源。
    • 一个进程请求当前被另一个进程占有的一个资源,则操作系统可以抢占另一个进程(如果请求进程的优先级高),要求它释放资源。只有在任意两个进程的优先级都不相同的条件下,方法二才能预防死锁
  4. 破坏环路等待条件

    • 保证每一个进程在任何时刻只能占用一个资源,如果要请求另外一个资源,它必须先释放第一个资源。
    • 所有资源统一编号。如下图所示,其规则是:进程在任何时刻都可以提出资源请求,但是所有请求必须按照资源编号提出。也就是说进程可以线请求打印机后请求磁带机,但不可以先请求绘图仪后请求打印机。尽管能够消除死锁问题,但在大型的操作系统中找不出一种可行的编号次序,潜在的资源及各种不同用途的数目会变得很大,以至于使编号方法根本无法使用。

在这里插入图片描述
上述四种方法各有缺陷,一般不使用!!

死锁检测

每种类型一个资源的死锁检测

​ 假设一个系统包括A到G共7个进程,R到W共6种资源。资源的占有情况和进程对资源的请求情况如下:

  1. A进程持有R资源,且需要S资源

  2. B进程不持有任何资源,但需要T资源

  3. C进程不持有任何资源,但需要S资源

  4. 在这里插入图片描述
    ​ 那么,显然进程D、E、G形成了一个环,陷入了死锁状态。虽然肉眼可轻易判断是否存在环,但是计算机不能这样子判断,需要一个正规的算法。具体算法如下,假设对已经检查过的弧(有向边)进行标记,以避免重复检查:

  5. 对图中的每一个节点N,将N作为起始点执行以下5个步骤

  6. 将L初始化为空表,并清除所有的有向边标记

  7. 将当前节点添加到L的尾部,并检测该结点是否在L中出现过两次。如果是,那么该图包含了一个环(已在列中),算法结束。

  8. 从给定的结点开始,检测是否存在没有标记的从该结点出发的弧(有向边)。如果存在的话,将执行第五步;如果不存在,则执行第六步

  9. 随机选取一条没有标记的从该结点出发的弧(有向边),并标记。然后顺着这条弧线找到新的当前节点,并返回到第3步。

  10. 如果这一节点是起始节点(回溯得到的),那么表明该图不存在任何环,算法结束。否则意味着我们走进了死胡同(第4个条件限制的,说明已经没有了新弧),所以需要一走该节点,返回到前一个节点,即当前节点前面的一个节点,并将它作为新的当前节点,同时转向第三步。

​ 以上图为例,首先将R放入空表中,并移动到唯一可能的节点A,将A添加到L中。然后到达S,但是S不能往下走了,此时L={R,A,S},只能进行回溯,一直回溯到A,表示该部分不存在环,算法结束。那么现在已B节点开始,一直到D,这是L={B,T,E,V,G,U,D}。现在必须随机选择,如果选S点,那么走进了死胡同并回溯到D,选T接着将L更新为L={B,T,E,V,G,U,D,T},发现了环的出现,算法结束

每种类型多个资源的死锁检测——类似银行家算法

​ 类似于银行家算法,给出两个矩阵,分别表示的是已分配到的资源以及需要的资源

  1. 寻找一个没有标记的进程 Pi,要求它所请求的资源小于等于剩余资源量。
  2. 如果找到了这样一个进程,就将其占有的资源量加到剩余资源量中,并标记该进程,转回第 1 步。
  3. 如果没有找到这样一个进程,那么算法结束。

算法结束时,所有没有标记过的进程(如果存在)都是死锁进程

死锁避免

安全状态和不安全状态

​ 在图6-9a中有一个A拥有3个资源实例,但最终需要9个实例的状态;而B当前拥有两个资源实例,将来共需要4个资源实例。同样,C拥有2个资源实例,还需要另外5个资源实例。总共有10个资源实例,其中有7个资源已经分配,还有另外三个资源是空闲的。

在这里插入图片描述

​ 图6-9a的状态是安全的,这是由于存在一个分配序列是的所有的进程都能完成!!

首先把空闲的3个中的两个分配给B,B结束后返回4个资源,此时空闲的共有5个资源;那么把5个空闲资源分给C,C结束后返回7个资源,此时空闲资源有7个;那么最后把7个分配给A,A恰好能完成。那么在这种调度方式中,这三个进程不会有存在任何资源争夺问题,可以说明这个状态是安全的!

​ 假设现在的状态如图6-10a所示,按照以下形式对资源进行分配,6-10d陷入了困境之中,从安全状态进入到了不安全状态中,需要回过头来进行调整!!!在这里插入图片描述​ 需要注意!不安全状态并不是死锁!!A可以释放一个资源等C完成后,从而避免死锁!!​ 安全状态和不安全状态的区别是:从安全状态出来,系统能够保证所有进程都能完成;而从不安全状态出发,就没有这样的保证!!

单个资源的银行家算法

​ 在6-11a中看到4个客户A、B、C、D,每个客户都被授予一定数量的贷款,银行家知道不可能所有客户同时都需要最大贷款额,所以只保留10个单位而不是22个单位的资金来为客户服务。这里将客户比作进程,贷款比作资源,银行家比作成操作系统!
在这里插入图片描述
​ 在6-11b中,银行家能够拖延除了C以外的其他请求,让C先完成,然后释放C所占的4个单位资源。有了这4个单位资源,银行家就可以给D或B分配所需的贷款单位,以此类推。

多个资源的银行家算法

​ 可将单个资源的银行家算法进行推广已处理多个资源
​ 下图中三个向量分别表示现有资产E已分配资源P可用资源A
E i = P i + A i E_i = P_i + A_i Ei=Pi+Ai在这里插入图片描述检查一个状态是否安全的算法如下:

  1. **查找右边矩阵中是否存在一行,其没有被满足的资源数均小于或等于A。如果不存在这样的行,那么系统将会死锁,因为任何进程都无法运行结束(**确认进程会一直占有资源直到它们终止为止)。
  2. 假若找到这样一行,那么可以假设它获得所需的资源并运行结束,将该进程标记为终止,并将资源加到向量A上
  3. 重复以上两步,或者直到所有进程都标记为终止,其初始状态是安全的;或者所有进程的资源需求都得不到满足,此时就是发生了死锁

如果在第一步中同时有若干进程均符合条件,那么不管挑选哪一个运行都没有关系,因为可用资源或者会增多,或者至少保持不变,但一定不会减少!!!

死锁恢复

一旦检测出死锁,就应该立即采取措施来接触死锁。死锁解除的主要方法有:

  • 资源剥夺法。 挂起某些死锁进程,抢占它的资源,分配给其他死锁进程。
  • 撤销进程法。 强制撤销部分进程并剥夺这些进程的资源,让其他进程顺利执行。
  • 进程回退法。
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值