死锁与饥饿

来源:互联网 发布:linux 打印程序 开发 编辑:程序博客网 时间:2024/04/29 14:57

第五章  死锁与饥饿

 

学习指导:

死锁是操作系统的棘手问题,因为不存在处理死锁的完美方法。从理论上来说,如果给定进程有关资源的命令序列,可以给出避免死锁的充分必要算法,尽管其开销很大(NP完全),但实际以序列形式给出的资源需求对于稍微复杂一点的程序都是不现实的。

本章介绍的预防、避免、检测与恢复策略,在大多数实际系统中并未采用,一方面因为开销,另方面因为使用的方便性。

然而本章内容仍是重要的,尤其是死锁避免与检测。包括安全状态与安全序列的定义和检查算法、避免死锁的资源分配算法。读者应当认真区分死锁避免算法与死锁检测算法之间的本质差别,尽管这两个算法在结构上很相似,差别只在NeedWork的比较和RequestWork的比较。

饥饿与饿死反映了资源分配策略的不公平性,应当从进程状态方面理解饥饿与死锁之间的差别。

 

习题解答:

1.  下面关于死锁问题的叙述哪些是正确的,哪些是错误的,说明原因。

        (1) 参与死锁的所有进程都占有资源;

        (2) 参与死锁的所有进程中至少有两个进程占有资源;

        (3) 死锁只发生在无关进程之间;

(4) 死锁可发生在任意进程之间。

答:说法(1)是错误的,应该是参与死锁的所有进程都等待资源。如下图所示,参与进程p1p2p3p4,尽管p3p4不占有资源,但也卷入死锁

p1

p2

p3

p4

 


 

 

 

 

 

    说法(2)正确。 参与死锁的进程至少有两个,设为p1,p2p1占有资源r1而等待资源r2p2占有资源r2而等待资源r1

说法(3)错误。死锁也可能发生在相关进程之间,如p1p2也可能是相关进程。

说法(4)正确,死锁既可能发生在相关进程之间,也可能发生在无关进程之间。即死锁可发生在任意进程之间。

 

2.  试证明当每个资源类中仅有一个资源实例时,资源分配图中的环路是死锁的充要条件。

证明:已知必要条件成立,即发生死锁必存在环路,下面只需证明充分条件,即在每类资源仅有一个实例的前提下,环路意味着死锁。

假定环路上共有k个进程(k³2),设这k个进程为p1,p2,…,pkp1等待p2占有的资源r1p2等待p占有的资源rpk等待p占有的资源rk。显然,这k个资源类中的所有资源实例均被环路上的进程所占有,环路外的进程有关资源的任何释放动作必不涉及这k类资源,因而无法使环路上的等待进程解除等待状态,因而这k个进程将无限期地等待下去,即发生死锁。证毕。

 

3.  什么叫饥饿?什么叫饿死?什么叫活锁?举例说明之.

答:在一个动态系统中,资源请求与释放是经常性发生的进程行为。对于每类系统资源,操作系统需要确定一个分配策略,当多个进程同时申请某类资源时,由分配策略确定资源分配给进程的次序。资源分配策略可能是公平的(fair),能保证请求者在有限的时间内获得所需资源;资源分配策略也可能是不公平的(unfair),即不能保证等待时间上界的存在。在后一种情况下,即使系统没有发生死锁,某些进程也可能会长时间等待。当等待时间给进程推进和响应带来明显影响时,称发生了进程饥饿(starvation),当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死(starve to death)

考虑一台打印机分配的例子,当有多个进程需要打印文件时,系统按照短文件优先的策略排序,该策略具有平均等待时间短的优点,似乎非常合理,但当短文件打印任务源源不断时,长文件的打印任务将被无限期地推迟,导致饥饿以至饿死。

与饥饿相关的另外一个概念称为活锁(live lock),在忙式等待条件下发生的饥饿,称为活锁。例如不公平的互斥算法。

 

4.  死锁与饿死之间有何相同点和不同点?

答:饿死与死锁有一定联系:二者都是由于竞争资源而引起的,但又有明显差别,主要表现在如下几个方面:

(1) 从进程状态考虑,死锁进程都处于等待状态,忙式等待(处于运行或就绪状态)的进程并非处于等待状态,但却可能被饿死;

(2) 死锁进程等待永远不会被释放的资源,饿死进程等待会被释放但却不会分配给自己的资源,表现为等待时限没有上界(排队等待或忙式等待)

(3) 死锁一定发生了循环等待,而饿死则不然。这也表明通过资源分配图可以检测死锁存在与否,但却不能检测是否有进程饿死;

(4) 死锁一定涉及多个进程,而饥饿或被饿死的进程可能只有一个。

饥饿和饿死与资源分配策略(policy)有关,因而防止饥饿与饿死可从公平性考虑,确保所有进程不被忽视,如FCFS分配算法。

 

5.  何谓银行家算法的保守性? 举例说明之。

答:银行家算法的保守性是指银行家算法只给出了进程需要资源的最大量,而所需资源的具体申请和释放顺序仍是未知的,因而银行家只能往最坏处设想.

考虑资源集合R={A(1),B(1)},进程集合P={p1,p2},已知进程p1和进程p2的活动序列分别为:p1a,b,,; p2b,,b,a,, 显然p1p2的资源最大需求量均为A(1)B(1) 假定某时刻系统状态如下:

               Claim      Allocation      Need      Available

               A   B       A   B         A   B       A   B

          p1:  1   1       1   0          0   1       0   1

          p2:  1   1       0   0          1   1

 

即此时p1a被系统接受。其后系统接收到的命令有两种可能,一是p1的请求b,二是p2的请求b。 假定为p2的请求b,因Request[2]=(0,1)£Need[2]=(1,1),故该请求是合法的。又Request[2]=(0,1)£Available=(0,1),故该请求系统当前能够满足。假定分配,系统状态变化如下:

               Claim      Allocation      Need      Available

               A   B        A   B         A   B       A   B

         p1:  1   1        1   0         0   1        0   0

          p2:  1   1        0   1         1   0

 

运行安全性检测算法发现此时系统处于不安全状态,因而取消分配,p2等待。实际上如果真正实施分配系统并不会进入死锁状态,因为分配后按照p2(),p1(b),p1(),p1(),p2 (b),p2(a),p2(),p2()的次序两个进程可以执行完,这是一个p1p2交叉执行的次序,而不是一个顺序执行的次序,银行家算法不能判断。

 

6.  能否给出避免死锁的充要性算法? 为什么?

答:目前关于避免死锁的算法,如银行家算法是充分性算法,即确保系统时刻处于安全状态,这是在系统已知每个进程所需资源最大量的条件下可以给出的最好结果。

如果系统不仅知道每个进程所需资源的最大量,而且知道进程有关资源的活动序列,在这个更强的条件下,则可以给出避免死锁的充要性算法(读者可以证明),但其复杂度是很高(NP完全)的。而且由于程序中分支和循环的存在,事先给出进程有关资源的命令序列一般是不可能的。

 

7.  设有一个T型路口,其中ABCD处各可容纳一辆车,车行方向如下图所示,试找出死锁并用有序分配法消除之。要求资源编号合理。

 

A

B

¬ E:左转

W:直行 ®

D

C

 

文本框: S: 左转

 

­

 

 

 

 

 

解:(1)E方向两台车分别位于ABS方向一台车位于CW方向一台车位于D(2)S方向两台车分别位于BCE方向一台车位于AW方向一台车位于D

设位置资源CBAD的编号从低到高依次为1234,管理四个位置的信号量分别为s1,s2,s3,s4,信号量的初值均为1车辆活动如下:

 

semaphore s1=1,s2=1,s3=1,s4=1;

W:直行

P(s1); //按序申请

P(s4);

驶入D;

驶入C;

V(s4);

驶出C;

V(s1);

E:左转

P(s2);

驶入B;

P(s3)

驶入A;

V(S2)

P(s4)

驶入D;

V(s3)

驶出D;

V(s4);

S:左转

P(s1);

驶入C;

P(s2)

驶入B;

V(S1)

P(s3)

驶入A;

V(s2)

驶出A;

V(s3);

 

8.  设系统中仅有一个资源类,其中共有M个资源实例,使用此类资源的进程个数共有N个,它们所需资源最大量总和为S,试证明发生死锁的必要条件是S³M+N

证明:假定发生死锁,且参与死锁的进程个数为n(2£n£N),参与死锁的n个进程已经占有系统中全部M个资源实例,而还没够(因它们处于无限期等待状态),每个进程至少还需要一个资源实例,因而参与死锁进程所需要资源总量³Mn

每个未参与死锁进程至少需要一个资源实例(若不需要则不属于N集合中,它们没有参与死锁是因为它们在得到并使用完资源后已经将其释放),由于共N-n未参与死锁的进程,它们所需资源总量³N-n

由此可知,全部进程所需要的资源总量S³(M+n)+(N-n)=M+N

 

9.  在银行家算法中,若出现如下资源分配情况:

        Allocation           Need           Available     

           A  B  C  D      A  B  C  D      A  B  C  D

     P0:  0  0  3  2      0  0  1  2      1  6  2  3

         P1:  1  0  0  0      1  7  5  0

         P2:  1  3  5  4      2  3  5  6

         P3:  0  3  3  2      0  6  5  2

         P4:  0  0  1  4      0  6  5  6

试问:(1)当前状态是否安全?

      (2)如果进程P2提出安全请求Request[2]=(1,2,2,2),系统能否将资源分配给它?说明原因.

解:(1)当前状态是安全状态。

运行安全性检查算法如下:

    1Work = AvailableFinish = false

    2)寻找满足如下条件的i:

       Finish[i]==false并且Need[i]Work[i]

       如果不存在,则转步骤4);

    3Work = Work + Allocation[i]Finish[i] = true

       转步骤2

4)如果对于所有iFinish[i] = true,则系统处于安全状态,否则处于不安全状态。

 

Work = Available=1, 6, 2, 3

运行安全性检测算法,Finish[0]=false并且Need[0]=(0 0 1 2)<Work,

Work = Work + Allocation[0]=1, 6, 2, 3+0, 0, 3, 2=1, 6, 5, 5);Finish[0] = true

Finish[3]=false并且Need[3]=0, 6, 5, 2<Work,

Work = Work + Allocation[3]=1, 6, 5, 5+0, 3, 3, 2=1, 9, 8, 7);Finish[3] = true

Finish[4]=false并且Need[4=0, 6, 5, 6<Work,

Work = Work + Allocation[4]=1, 9, 8, 7+0, 0, 1, 4 =1, 9, 9, 11);Finish[4] = true

Finish[1]=false并且Need[1]=1, 7, 5, 0<Work,

Work = Work + Allocation[4]=1, 9, 9, 11+(1, 0, 0, 0 )=(2, 9, 9, 11)Finish[1] = true

Finish[2]=false并且Need[2]=2, 3, 5, 6<Work,

Work = Work + Allocation[4]=2, 9, 9, 11+1, 3, 5, 4 =3, 12, 14, 15);Finish[2] = true

 

可以找到一个安全进程序列<p0,p3p4p1,p2>,它使Finish[i]=true,对于所有0i4,因而可以断言系统当前处于安全状态.

2)运行银行家算法,由于Request[2]=1, 2, 2, 2£Need[2]=2, 3, 5, 6),因而请求合法。进一步,Request[2]=1, 2, 2, 2£Available=1, 6, 2, 3),故该请求是可以满足的。假设将资源分配给p2,则系统状态变为:

        Allocation           Need           Available     

           A  B  C  D      A  B  C  D      A  B  C  D

     P0:  0  0  3  2      0  0  1  2      0  4  0  1

         P1:  1  0  0  0      1  7  5  0

         P2:  2  5  7  6      1  1  3  4

         P3:  0  3  3  2      0  6  5  2

         P4:  0  0  1  4      0  6  5  6

运行安全性检测算法,Work=Available=0, 4, 0, 1),Finish[i]=false,此时所有Need[i]£Work[i]均不成立,结果Finish[i]均为false,不存在安全进程序列,系统处于不安全状态。系统将取消资源分配并恢复原来状态,进程p2等待。

 

10某系统采用死锁检测手段发现死锁,设系统中资源类集合为{ABC},资源类A中共有8个实例,资源类B中共有6个实例,资源类C中共有5个实例.又设系统中进程集合为{p1,p2,p3,p4,p5,p6},某时刻系统状态如下:

 

         Allocation         Request          Available

        A   B   C      A   B   C        A   B   C

  p1:    1   0   0       0   0    0       2    2   1

  p2:    3   2   1       0   0    0

  p3:    0   1   2       2   0    2

  p4:    0   0   0       0   0    0

  p5:    2   1   0       0   3    1

  p6:    0   0   1       0   0    0

(1)    在上述状态下系统依次接受如下请求:Request[1]=(1,0,0)Request[2]=(2,1,0)   Request[4]=(0,0,2)。给出系统状态变化情况,并说明没有死锁。

(2)    在由(1)所确定的状态下系统接收如下请求:Request[1]=(0,3,1),说明此时已发生死锁,并找出参与死锁的进程。

解:(1如果系统只是接受请求,但是没有分配资源给进程,那么系统状态变为:

         Allocation         Request          Available

        A   B   C      A   B   C        A   B   C

  p1:    1   0   0       1   0    0       2    2   1

  p2:    3   2   1       2   1    0

  p3:    0   1   2       2   0    2

  p4:    0   0   0       0   0    2

  p5:    2   1   0       0   3    1

  p6:    0   0   1       0   0    0

在该状态下运行死锁检测算法,可以找到一个进程序列<p4,p1,p2,p3,p5,p6>,它使Finish[i]=true,对于所有1i6,因而可以断言系统当前没有进入死锁状态。

如果系统接受请求后,将一个A分配给进程p1,则系统状态变为:

         Allocation         Request          Available

        A   B   C      A   B   C        A   B   C

  p1:    2   0   0       0   0    0       1   2   1

  p2:    3   2   1       2   1    0

  p3:    0   1   2       2   0    2

  p4:    0   0   0       0   0    2

  p5:    2   1   0       0   3    1

  p6:    0   0   1       0   0    0

在该状态下运行死锁检测算法,可以找到一个进程序列<p4,p1,p2,p3,p5,p6>,它使Finish[i]=true,对于所有1i6,因而可以断言系统当前没有进入死锁状态。

2)设在(1)的状态下系统接收如下请求:Request[1]=(0,3,1),则系统状态变为:

         Allocation         Request          Available

        A   B   C      A   B   C        A   B   C

  p1:    1   0   0       1   3    1       2    2   1

  p2:    3   2   1       2   1    0

  p3:    0   1   2       2   0    2

  p4:    0   0   0       0   0    2

  p5:    2   1   0       0   3    1

  p6:    0   0   1       0   0    0

在该状态下运行死锁检测算法,可以找到一个进程序列<p4,p2,p3,p5,p6,p1>,它使Finish[i]=true,对于所有1i6,因而可以断言系统当前没有进入死锁状态.

设在(1)的状态下系统接收如下请求:Request[1]=(0,3,1),则系统状态变为:

         Allocation         Request          Available

        A   B   C      A   B   C        A   B   C

  p1:    2   0   0       0   3    1       1    2   1

  p2:    3   2   1       2   1    0

  p3:    0   1   2       2   0    2

  p4:    0   0   0       0   0    2

  p5:    2   1   0       0   3    1

  p6:    0   0   1       0   0    0

在该状态下运行死锁检测算法,找不到一个进程序列使Finish[i]=true,对于所有1i6,因为存在i∈{1235},使Finish[i]=false,因而可以断言系统已经进入死锁状态,进程p1,p2,p3,p5卷入死锁.

 

11.  设有7个简单资源: ABCDEFG。 其申请命令分别为abcdefg; 释放命令分别为、、、、、、; 又设系统中有P1P2P3三个进程,其活动分别为:

      P1活动: a b   e f g   

      P2活动: b c   d a  

P3活动: c d  e g f   

试分析当P1P2P3并发执行时,是否有发生死锁的可能性,并说明原因。

解:不会有发生死锁的可能性。死锁的四个必要条件是:(1) 资源独占(mutual exclusion)    (2) 不可剥夺(no-preemption)(3) 保持申请(hold and wait)(4) 循环等待(circular wait)

在本题中,进程p1p2都使用的资源集合是{a,b},由于进程p2在申请a之前已经释放了b,不存在占有b并且申请a的情况,所以进程p1p2之间不满足死锁的四个必要条件,不会产生死锁;

进程p1p3都使用的资源集合是{e,f,g},进程p1p3都是先申请资源e,这两个进程同时申请资源,那么只能有一个进程先获得e,另一个进程将因为得不到e而阻塞,获得e的进程将进一步顺利获得资源fg,从而运行结束,释放资源e,fg,唤醒另一个进程运行。可见,进程p1p3之间不会产生死锁;

进程p2p3都使用的资源集合是{c,d},由于进程p2在申请d之前已经释放了c,不存在占有c并且申请d的情况,所以进程p2p3之间不满足死锁的四个必要条件,不会产生死锁。

综上所述,当P1P2P3并发执行时,没有发生死锁的可能性。

 

原创粉丝点击