死锁(操作系统)
Posted 每天告诉自己要努力
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了死锁(操作系统)相关的知识,希望对你有一定的参考价值。
死锁: 各进程互相等待对方手里的资源,导致各进程都阻塞,无法向前推进的现象。
死锁一定是“循环等待对方手里的资源”导致的,因此如果有死锁现象,那么至少有两个或者两个以上的进程同时发生死锁。另外,发生死锁的进程一定是处于阻塞状态。
饥饿:
由于长期得不到想要的资源,某进程无法向前推进的现象。(比如在短进程优先SPF算法中,如果一直有短进程到来,则长进程一直得不到处理机,从而发生长进程“饥饿”);
可能只有一个进程发生饥饿。发生饥饿的进程可能是阻塞态(如长期得不到需要的IO设备),也可能是就绪态(比如长期得不到处理机)。
死循环:
某进程执行过程中一直跳不出某个循环的现象。有时候是因为程序逻辑bug导致,也可能是程序员估计设计的。可能只有一个进程发生死循环。死循环的进程可以上处理机运行(可以是运行态),只是无法像期待的那样顺利推进。死锁和饥饿是由于操作系统分配资源的策略不合理导致的,而死循环是由代码逻辑的错误导致的。
死锁和饥饿是管理者(操作系统)的问题,死循环是被管理者的问题。
死锁产生的必要条件
必须同时满足四个条件,只要有一个条件不成立,死锁则不会发生。
- 互斥条件: 并发执行的进程只有对必须互斥使用的资源的争抢才会导致死锁(如哲学家的筷子,打印机设备)。但是像内存、扬声器这样可以同时让多个进程使用的资源是不会导致死锁的(因为进程不用阻塞等待这种资源)。
- 不可剥夺条件: 进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放。(如哲学家的筷子只有他自己可以放回去,别人不能抢走他的筷子)
- 保持和请求条件:进程已经保持了至少一个资源,但同时又请求了一个新的且同时被其他进程占有的资源,此时请求新资源的进程被阻塞,但是又对自己已经占有的资源保持不放。
- 循环等待条件: 存在一种进程资源的循环等待链,链中每一个进程自己已经获得了的资源同时被下一个进程所请求。
注意:
发声死锁的时候一定有循环等待,但是发声循环等待的时候未必发生死锁(循环等待是死锁的必要不充分条件)。如果同类资源数大于1,则即使有循环等待,也未必会发生死锁。但是如果系统中每类资源都只有一个,那循环等待就是死锁的充分必要条件了(如哲学家问题中,当他们互相都拿起左边的筷子的时候,则发生死锁,但是此时如果多出了一个神秘哲学家,他可以给其中的一个哲学家的右手放一个筷子,这个神秘哲学家给他的筷子就是一个同类的、且可以替换掉他需要等待的那双筷子,因此死锁就不会发生了)
(即使发生了循环等待资源的现象,但是如果还有别的进程持有同类的可以替代的资源,死锁不一定发生。)
什么时候会发生死锁?
对不可剥夺资源的不合理分配,可能会导致死锁
1.对不可剥夺的资源(如打印机)进行抢夺竞争可能会引起死锁,对可剥夺资源(如CPU)的竞争是不会导致死锁的。
2.进程推进顺序非法。请教和释放资源的顺序不当,也同样会导致死锁。(比如进程A和进程B并发执行,A申请并占有了资源C,B申请 并占有了资源D,此时如果进程A申请已经被进程B占有的D资源,同时进程B申请被进程A占有的资源C,则A和B这两个进程都会因为要申请的资源被对方占有而阻塞,从而发生死锁)
3.信号量使用不当也会发生死锁。比如实现互斥的P操作必须要在实现同步的P操作之后,否则会发生死锁。
死锁的处理策略
1.预防死锁。破坏死锁产生的四个条件中的一个或者几个。
2.避免死锁。用某种方法防止系统进入不安全状态,从而避免死锁(银行家算法)。
3.死锁的检测和接触。允许死锁的发生,不过操作系统会负责检测出死锁的发生,然后采取某种措施接触死锁。
预防死锁
1.1破坏互斥条件(只有对必须互斥使用的资源进行争抢才会导致死锁)
如果能把互斥使用的资源改造成允许共享使用,则系统不会进入死锁状态。比如spooling技术:操作系统可以采用spooling技术把独占设备在逻辑上改造成共享设备。
该策略的缺点:并不是所有的资源都可以改造成可共享使用的资源。并且为了系统的安全,很多地方还必须保护这种互斥性。因此,很多时候都无法破坏互斥条件。
1.2破坏不剥夺条件(进程所获得的资源在没有使用完之前,不能被其他进程强行夺走,只能由他自己主动释放) 方案一:当某个进程请求新资源时得不到满足,它必须立即释放保持的所有资源,等到之后需要的时候再重新申请。也就是说,即使某些资源尚未用完,也需要主动释放,从而破坏了不可剥夺条件。
方案二:当某个进程需要的资源正在别其他进程占用,可以由操作系统协助,将想要的资源强行夺走。这种方式一般需要考虑各进程的优先级(比如:剥夺调度方式,就是将处理机资源强行剥夺给优先级更高的进程使用)该策略的缺点:
实现起来比较复杂。释放已经获得的资源可能会造成前一阶段的工作实效。因此这种做法一般只适用于易保存和回复状态的资源,如cpu;反复申请和释放资源会增加系统开销。若采取方案一,意味着得不到某个资源的话,那么之前所获得的资源就要被丢掉,之后再重新申请,如果一直发生这样的情况,就可能导致进程饥饿。
1.3破坏请求和保持条件 方案一:采用静态分配方法,即进程在运行前,一次性申请完它所需要的全部资源,在他的资源未满足之前不让这个进程投入运行。一旦投入运行,证明进程已经拥有它所需要的所有资源,这些资源在运行后一直归他所有,该进程就不会再请求别的资源了。
该策略的缺点:有些资源可能只需要很短的时间,因此如果进程的整个运行期间都一直保持着所有资源,就会造成资源的严重浪费,资源利用率极低。另外,该策略也可能导致某些进程饥饿,因为有的需要的资源会一直被其他进程占有。
1.4破坏循环等待条件 可采用顺序资源分配法。首先给资源中的资源分配编号,规定每个进程必须按照编号递增的顺序依次请求资源,同类资源(编号相同的资源)必须一次申请完。
原理分析:一个进程只有已占有小编号的资源时,才有资格占有更大编号的资源。按此规则,已持有大编号的资源的进程不可能逆向回来申请小编号的资源,从而就不会产生循环等待的现象。
回头想想哲学家就餐问题里面破坏了哪几种方法?(提示,四种里有三种都在哲学家问题里面用到了)
避免死锁
什么是安全序列?
如果系统处于安全状态,就一定不会发生死锁。否则,就可能发生死锁,只是可能。
(处于不安全状态未必就是发生了死锁,但是发生了死锁就一定是在不安全状态)
因此可以在分配资源之前预先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应进程的分配请求。这也是“银行家算法”的核心思想。
死锁的检测与解除
以上是关于死锁(操作系统)的主要内容,如果未能解决你的问题,请参考以下文章