操作系统之死锁

在看死锁之前,先来看一张表格,这张表格对死锁,饥饿和死循环做了共同点和不同点的概述。

 共同点区别
死锁都是进程无法顺利向前推进的现象(故意设计的死循环除外)死锁一定是“循环等待对方手里的资源”导致的,因此如果有死锁现象,那至少有两个或两个以上的进程同时发生死锁。另外,发生死锁的进程一定处于阻塞态。
饥饿可能只有一个进程发生饥饿。发生饥饿的进程既可能是阻塞态(如长期得不到需要的I/O设备),也可能是就绪态(长期得不到处理机)
死循环可能只有一个进程发生死循环。死循环的进程可以上处理机运行(可以是运行态),只不过无法像期待的那样顺利推进。死锁和饥饿问题是由于操作系统分配资源的策略不合理导致的,而死循环是由代码逻辑的错误导致的。死锁和饥饿是管理者(操作系统)的问题,死循环是被管理者的问题

从上面的表格中,我们了解了死锁,饥饿和死循环的共同点和区别,接下来我们来看死锁的定义。

死锁的概念

1.死锁的定义

所谓死锁,是指多个进程因竞争资源而造成的一种互相等待,若无外力作用,这些进程都将无法向前推进。我之前有一篇文章的哲学家进餐问题就涉及到了死锁。

2.死锁产生的原因

(1)系统资源的竞争

通常系统中拥有不可剥夺的资源,其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局。例如打印机。

(2)进程推进顺序非法

进程在运行过程中,请求和释放顺序不当。例如并发进程P1和P2分别拥有资源R1和R2,而进程P1申请资源R2、进程P2申请资源R1,两者都会因为所需资源被占用而阻塞。在前面有一文中,提到过信号量只用不当也会造成死锁。例如进程A等待进程B发的消息,进程B又在等待进程A发的消息,可以看出进程A和B不是因为竞争同一资源,而是在等待对方的资源时导致死锁。

(3)死锁产生的必要条件

即产生死锁一定得同时满足以下4个条件,只要其中一个条件不成立,死锁就不会发生。

互斥条件。

不剥夺条件:进程所获得的资源在未使用完之前,不能被其他进程强行夺走。

请求并保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放

循环等待条件:存在一种进程资源的循环等待链,链中每个进程已获得的资源同时被链中下一个进程所请求。即存在一个处于等待态的进程集合{P1,P2,...,Pn},其中Pi等待的资源被Pi+1(i=0,1,...,n-1)占有,Pn等待的资源被P0占有,如下图(图来自王道操作系统课本)

从上面看循环等待,可能会感觉和死锁的定义有点像,但是还是不一样的。我可以增加一个不在圈内的Pk,若Pk释放了输出设备,则可以打破循环等待。只有当每类资源都只有一个的时候,才会变成死锁的充分必要条件。

死锁的处理策略

为使系统不发生死锁,必须设法破坏产生死锁的4个必要条件之一,或允许死锁产生,但当死锁发生时能检测出死锁,并有能力恢复。

1.死锁预防

设置某些条件,破坏4个必要条件其中的一个或者几个,以防止发生死锁。

2.避免死锁

在资源的动态分配的过程中,用某种方法防止系统进入不安全状态,从而避免死锁

3.死锁的检测及解除

无须采取任何限制性措施,允许进程在运行过程中发生死锁。通过系统的检测机构及时地检测出死锁的发生,然后采取某种措施解除死锁

死锁预防

防止死锁的发生只需要破坏死锁产生的4个必要条件之一即可

1.破坏互斥条件

若允许系统资源都能共享使用,则系统不会进入死锁状态。但是有些资源不能同时访问,比如打印机,所以,破坏互斥条件而预防死锁的方法不太可行。

2.破坏不剥夺条件

当一个已保持了某些不可剥夺资源的进程请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待一会需要时再重新申请。

该策略实现起来比较复杂,反复申请和释放会增加系统开销,降低系统吞吐量。这种方法常用于易于保存和恢复的资源,如CPU的寄存器及内存资源,一般不能用于打印机这种。

3.破坏请求并保持条件

采用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。一旦投入运行,这些资源一直归它所有,不再提出其他资源请求,这样就可以保证系统不会发生死锁。

这种方式实现简单,但缺点也显而易见,系统资源被严重浪费,其中有些资源在一开始才会使用,或者根本不会使用。容易导致“饥饿”现象,由于个别资源长期被其他进程占用时,将致使等待该资源的进程迟迟不能开始运行。

4.破坏循环等待条件

采用顺序资源分配法。首先给系统中的资源编号,规定每个进程必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源Ri,则该进程在一会的资源申请中就只能申请编号大于Ri的资源

这种方法存在的问题是,编号必须相对稳定,这就限制了新类型设备的增加;尽管在为资源编号时已考虑到大多数作用实际使用这些资源的顺序,但也经常会发生作用使用资源的顺序与系统规定顺序不同的情况,造成资源的浪费;此外,这种按规定次序申请资源的方法,也必然会给用户的变成带来麻烦。

死锁避免

死锁的避免同样属于事先预防策略,但这不是去破坏四个必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,以不免发生死锁。这种方法所施加的限制条件较弱,可以获得比较好的系统性能。

1.系统安全状态

所谓安全状态,是指系统能按某种进程推进(P1,P2,...,Pn)为每个进程Pi分配其所需的资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利完成。此时P1,P2,...,Pn为安全序列。用下表中的数据举个例子,假设有三个进程P1,P2和P3,共有12台磁带机。进程P1供需要10台,P2和P3分别需要4台和9台。假设在T0时刻,进程P1,P2和P3已分别获得5台,2台和2台,尚有3台未分配。

进程最大需求已分配可用
P11053
P242 
P392 

 

在T0时刻是安全的,因为存在一个安全序列P2,P1,P3,只要系统按此进程序列分配资源,那么每个进程都能顺利完成。也就是说,当前可用磁带机为3台,先把3台磁带机分配给P2以满足最大需求,P2结束并归还资源后,系统有3+2=5台磁带机,接下来分配给P1进程,那么P1结束归还后有5+5=10台磁带机。那么我现在有10台,我分配7台给P3,这样P3也能顺利完成。这样就形成一个安全序列。

通过上面,因此可以在资源分配之前预先判断这次分配是否会导致系统进入不安全状态以此决定是否答应资源分配

这里要明白一个道理,并非所有的不安全状态都是死锁状态,但是当系统进入不安全状态后,便可能进入死锁状态;与之相反,只要系统处于安全状态,系统便可避免进入死锁状态。

避免死锁有一个著名的算法,那就是银行家算法,我有一篇单独的文章论述到了银行家算法,详情可以移步。

死锁检测和解除

前面的都是在死锁出现之前施加限制条件或进行检测,若系统为进程分配资源时,不采取任何措施,则应该提供死锁检测和解除的手段。

1.资源分配图

系统死锁可利用资源分配图来描述。下图就是一个资源分配图(图来自于王道操作系统课本),用圆圈代表一个进程,用框代表一类资源。由于一类资源可能有多个,因此用框中的一个圆代表代表一类资源中的一个资源。从进程到资源的有向边称为请求边,表示该进程申请一个单位的该类资源;从资源到进程的边成为分配边,表示该类资源已有一个资源分配给该进程。

在下图中进程P1得到了R1送过来的两个资源,并且向R2请求了一个资源;进程P2分到了R2送过来的一个资源,又向R1请求一个资源。

                      图1

2.死锁定理

简化资源分配图可以检测系统状态S是否为死锁状态。简化方法如下:

1)在资源分配图中,找出既不阻塞又不孤立点的进程Pi(即找出一条有向边与它相连,且该有向边对应资源的申请数量小于系统中已有的空闲资源数量,如在上图中,R1没有空闲资源,R2有一个空闲资源。若所有连接该进程的边均满足上述条件,则这个进程能继续运行直至完成,然后释放它所占有的所有资源)。消去它所有的请求边和分配边,使之成为孤立的结点。在上述中P1满足,或者消去P1所有的边,得到下图(图来自王道书本)。

                            图 2

注:这里判断资源是否有空间,是用资源数-资源的出度(出度在数据结构的图中有,理解为从资源指向进程的箭头,比如图1的资源R1,有两个指向P1的箭头,一个指向P2的箭头,那么它的出度就是3,空间=原来的资源数-出度=3-3=0,所以它资源是分配完了的,R2的话是有一个空闲资源的)。

2)进程释放所有的资源,可以唤醒某些因等待这些资源而阻塞的进程,原来的阻塞进程可能变为非阻塞进程。比如图2,我现在释放掉P1本来占用的资源,那么这时R1资源还有2个,R2资源还有一个,P2向R1申请一个资源是可以的,因为它还有两个资源,根据1中的方法可以再次简化,得到下图。(若能消去图中所有的边,则称该图是可完全简化的。)

                     图 3

S为死锁的条件是当且仅当S状态的资源分配图是不可完全简化的,该条件为死锁定理。

3.死锁检测

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

1)资源剥夺发。挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源而处于资源匮乏的状态

2)撤销进程法。强制撤销部分甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程优先级和撤销进程代价的高低进行。

3)进程回退法。让一(或多)个进程回退到足以回避死锁的地步,进程回退时自愿释放资源而非被剥夺。要求系统保持进程的历史信息,设置还原点。

不过这个不太容易实现,还要多久能完成,进程已经使用了多少资源,交互式还是批处理都是一些问题。

如果上述中有什么表示错误或者理解错误,欢迎在评论区给我留言探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值