计算机操作系统-计算机系统中的死锁
在第二章中,我们已经涉及到死锁的概念,例如系统中只有一个扫描仪R1和一台刻录机R2,有两个进程p1和p2,他们都准备将扫描的文档刻录在CD光盘上,进程1先请求扫描仪R1并获得成功,进程2先请求刻录机R2也获得成功,后来P1又请求CD刻录机,因它已被分配给了P2而阻塞,P2又请求扫描仪,也因被分配给了进程1而阻塞,此时两个进程都被阻塞,双方都希望对方能释放出自己所需要的资源,但他们谁都因不能获得自己所需的资源去继续运行,从而无法释放出自己占有的资源,并且一直处于这样的僵持状态而形成死锁,又如,在第二章的哲学家进餐问题中,如果每个哲学家因饥饿都拿起了他们左边的筷子,当每一个哲学家又试图去拿起他们右边的筷子时,将会因为无筷子可拿而无限期地等待,从而产生死锁问题。接下来我们将对死锁发生的原因,如何预防和避免死锁等问题作较详细的介绍。
在系统中有许多不同类型的资源,其中可以引起死锁的主要是,需要采用互斥访问方法的、不可以被抢占的资源,即前面介绍的临界资源。系统中这类资源有很多,如打印机,数据文件,队列,信号量等。
可抢占性资源和不可抢占性资源
(1)可抢占性资源(可剥夺)
可把系统中的资源分成两类,一类是可抢占性资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统抢占。例如优先级高的进程可以抢占优先级低的进程的处理机。又如可把一个进程从一个存储区转移到另一个存储区,在内存紧张时,还可将一个进程从内存调出到外存上,即抢占该进程在内存空间,可见,CPU和主存均属于可抢占性资源。对于这类资源是不会引起死锁了。
(2)不可抢占性资源(非剥夺)
另一类资源是不可抢占性资源,即一旦系统把某资源分配给该进程,就不能将它强行收回,只能在进程用完后自行释放。例如,当一个进程已开始刻录光盘时,如果突然将刻录机分配给另一个进程,其结果必然会损坏正在刻录的光盘,因此只能等刻好光盘后由进程自己释放刻录机。另外磁带机,打印机等也都属于不可抢占性资源。
1.竞争不可抢占性资源引起死锁
2.竞争可消耗资源引起死锁
3.进程推进顺序不当引起死锁
死锁指两个或多个进程在执行过程中,因争夺资源而陷入相互等待的僵局,若无外力干预,这些进程将无法向前推进。此时,系统处于停滞状态,资源被无效占用。
虽然进程在运行过程中可能会发生死锁,但产生进程死锁是必须具备一定条件的,综上所述不难看出,产生死锁必须同时具备下面四个必要条件,只要其中任一个条件不成立,死锁就不会发生。
(1)互斥条件:进程对所分配到的资源进行排他性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其他进程请求该资源,则请求进程只能等待,直至占用该资源的进程用毕释放。
(2)请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
(3)不可抢占条件:进程已获得的资源在未使用之前不能被抢占,只能在进程使用完时由自己释放。
(4)循环等待条件:在发生死锁时,必然存在一个进程——资源的循环链,即进程集合(p0,p1,p2....pn)中的p0正在等待一个p1占用的资源,p1正在等待p2占用的资源,.....,pn正在等待已被p0占用的资源。
(1)预防死锁
(2)避免死锁
(3)检测死锁
(4)解除死锁
上述的四种方法,从(1)到(4)对死锁的防范程度逐渐减弱,但对应的是资源利用率的提高,以及进程因资源因素而阻塞的频度下降。
在死锁避免方法中,把系统的状态分为安全状态和不安全状态。当系统处于安全状态时,可避免发生死锁。反之,当系统处于不安全状态时,则可能进入死锁状态。
安全状态(Safe State):
系统存在至少一个安全序列(Safe Sequence),使得所有进程都能按此顺序依次获得所需资源并完成执行,而不会导致死锁。
不安全状态(Unsafe State):
不存在这样的安全序列。此时系统可能进入死锁,但不安全状态不一定会导致死锁(取决于后续资源请求的实际情况)。
虽然并非所有非安全状态都必然会转为死锁状态,但当系统进入不安全状态后,就有可能进入死锁状态(不一定)。反之,只要系统处于安全状态,系统便不会进入死锁状态。
进程 | 最大需求(Max) | 已分配(Allocated) | 剩余需求(Need = Max - Allocated) |
---|---|---|---|
P1 | 10 | 5 | 5 |
P2 | 4 | 2 | 2 |
P3 | 9 | 2 | 7 |
安全序列:P2→P1→P3(或其他可行顺序)。
结论:系统处于安全状态。
假设在初始状态下,进程 P3 先请求 1 个资源:
进程 | 最大需求 | 已分配 | 剩余需求 |
---|---|---|---|
P1 | 10 | 5 | 5 |
P2 | 4 | 2 | 2 |
P3 | 9 | 3 | 6 |
结论:无法找到安全序列 → 系统处于不安全状态。
此时系统会拒绝 P3 的资源请求,强制其等待,避免进入不安全状态。
1.银行家算法中的数据结构:
为了实现银行家算法,在系统中必须设置这样四个数据结构,分别用来描述系统中可利用的资源、所有进程对资源的最大需求,系统中的资源分配,以及所有进程还需要多少资源的情况。
(1)可利用资源向量Available。(可分配的)这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值时系统中配置的该类全部可用资源的数目,其数值随该类的资源的分配和回收而动态地改变。如果Available[j] = k,则表示系统中现有Rj类资源 K个。
(2)最大需求矩阵Max。这是一个n*m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=k,则表示进程i需要Rj类资源的最大数目为K。
(3)分配矩阵Allocation(已经分配的) 这也是一个n*m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j] = k,则表示进程i当前已分得Rj类资源的数目为k。
(4)需求矩阵Need。这也是一个n*m的矩阵,用来表示每一个进程尚需的各类资源数。如果Need[i,j]=k,则表示进程i还需要Rj类资源K个方能完成其任务。
Need[i,j] = Max[i,j]-Allocation[i,j]
当进程 Pi 请求资源时,系统执行以下步骤:
Step 1: 检查请求合法性
Step 2: 检查可用资源是否足够
一定要先满足上面的两个条件
Step 3: 模拟分配资源
Step 4: 执行安全状态检查
目标:判断是否存在一个安全序列,使得所有进程都能按顺序完成。
Step 1: 初始化
Step 2: 寻找可完成的进程
Step 3: 模拟进程完成
Step 4: 判断结果
假设系统有三种资源 R1、R2、R3,初始状态如下:
进程 | Max (R1, R2, R3) | Allocation (R1, R2, R3) | Need (R1, R2, R3) |
---|---|---|---|
P1 | (7, 5, 3) | (0, 1, 0) | (7, 4, 3) |
P2 | (3, 2, 2) | (2, 0, 0) | (1, 2, 2) |
P3 | (9, 0, 2) | (3, 0, 2) | (6, 0, 0) |
P4 | (2, 2, 2) | (2, 1, 1) | (0, 1, 1) |
P5 | (4, 3, 3) | (0, 0, 2) | (4, 3, 1) |
当前可用资源:Available=(3,3,2)(总资源数减去已分配资源)。
以上就是今天要讲的内容,我们简单的介绍了一下死锁,包括定义和产生死锁的必要条件,处理死锁的方法,包括详细讲了避免死锁的算法和系统安全状态等等,接下来会持续更新的,谢谢大家。