一、关于死锁
1.死锁基本概念
两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
2.死锁必备条件
(1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,
则请求者只能等待,直至占有资源的进程用毕释放。
(2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,
但又对自己已获得的其它资源保持不放。
(3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
(4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待
一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
3.死锁避免
避免死锁算法中最有代表性的算法是Dijkstra E.W于1968年提出的银行家算法。
银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要应多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,
对每一笔贷款,必须考察其是否能限期归还。在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,
必须保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。如果资源分配不得到就会发生进程循环等待资源,则进程
都无法继续执行下去的死锁现象。
把一个进程需要和已占有资源的情况记录在进程控制中,假定进程控制块PCB其中“状态”有就绪态、等待态和完成态。当进程在处于
等待态时,表示系统不能满足该进程当前的资源申请。“资源需求总量”表示进程在整个执行过程中总共要申请的资源量。显然,每个进程的
资源需求总量不能超过系统拥有的资源总数,银行算法进行资源分配可以避免死锁。
二、数据结构
可用资源向量available:这是一个含有m个元素的数组,其中的每一个元素代表一类可利用资源数目。
最大需求矩阵max:它是一个的矩阵,定义了系统中n个进程中得每一个进程对类资源的最大需求。
可分配矩阵allocation:这也一个的矩阵,定义了系统中每一类资源当前已分配给每一进程的资源数。
需求矩阵need:这表示每一个进程尚需的各类资源数。need[i][j]=max[i][j]-allocation[i][j]。
三、变量说明
可用资源向量available[3];
最大需求矩阵max[4][3];
可分配矩阵allocation[4][3];
需求矩阵need[4][3];
进程状态标识finish[4];
四、流程图
银行家算法的流程图
五、源代码
#include<stdio.h>
#define M 4
#define N 3
int available[3]={0,0,0};
int max[4][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
int allocation[4][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
int need[4][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
int request[3]={0,0,0};
void input()
{
int i=0,j=0;
printf("\t\t\t\tA B C\n");
printf("请输入进程0对3类资源的最大需求:");
for(j=0;j<3;j++)
{
scanf("%d",&max[0][j]);
}
printf("\n");
printf("请输入进程1对3类资源的最大需求:");
for(j=0;j<3;j++)
{
scanf("%d",&max[1][j]);
}
printf("\n");
printf("请输入进程2对3类资源的最大需求:");
for(j=0;j<3;j++)
{
scanf("%d",&max[2][j]);
}
printf("\n");
printf("请输入进程3对3类资源的最大需求:");
for(j=0;j<3;j++)
{
scanf("%d",&max[3][j]);
}
printf("\n");
printf("请输入进程0已分配的3类资源量:");
for(j=0;j<3;j++)
{
scanf("%d",&allocation[0][j]);
}
printf("\n");
printf("请输入进程1已分配的3类资源量:");
for(j=0;j<3;j++)
{
scanf("%d",&allocation[1][j]);
}
printf("\n");
printf("请输入进程2已分配的3类资源量:");
for(j=0;j<3;j++)
{
scanf("%d",&allocation[2][j]);
}
printf("\n");
printf("请输入进程3已分配的3类资源量:");
for(j=0;j<3;j++)
{
scanf("%d",&allocation[3][j]);
}
printf("\n");
printf("请输入可利用的3类资源量:");
for(j=0;j<3;j++)
{
scanf("%d",&available[j]);
}
for(i=0;i<4;i++)
for(j=0;j<3;j++)
{
need[i][j]=max[i][j]-allocation[i][j];
}
printf("\n");
}
void output()
{
int i=0,j=0;
printf("该时刻3类资源的分配情况如下:\n");
printf("\tMAX\t\tALOCAT\t\tNEED\t\tAVAILABLE\n");
printf("进程0:\t");
for(j=0;j<3;j++)
{
printf("%d ",max[0][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",allocation[0][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",need[0][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",available[j]);
}
printf("\n");
printf("进程1:\t");
for(j=0;j<3;j++)
{
printf("%d ",max[1][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",allocation[1][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",need[1][j]);
}
printf("\n");
printf("进程2:\t");
for(j=0;j<3;j++)
{
printf("%d ",max[2][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",allocation[2][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",need[2][j]);
}
printf("\n");
printf("进程3:\t");
for(j=0;j<3;j++)
{
printf("%d ",max[3][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",allocation[3][j]);
}
printf("\t");
for(j=0;j<3;j++)
{
printf("%d ",need[3][j]);
}
printf("\n");
}
void change(int n)
{
int j;
for(j=0;j<N;j++)
{
available[j]=available[j]-request[j];
allocation[n][j]=allocation[n][j]+request[j];
need[n][j]=need[n][j]-request[j];
}
}
int findmany()
{
int i=0,j=0,k=0,l=0;
i=allocation[0][0]+allocation[0][1];
i+=allocation[0][2];
j=allocation[1][0]+allocation[1][1];
j+=allocation[1][2];
k=allocation[2][0]+allocation[2][1];
k+=allocation[2][2];
l=allocation[3][0]+allocation[3][1];
l+=allocation[3][2];
if(i>=j)
{
if(i>=k)
{
if(i>=l)
return 0;
else
return 3;
}
else
{
if(k>=l)
return 2;
else
return 3;
}
}
else
{
if(j>=k)
{
if(j>=l)
return 1;
else
return 3;
}
else
{
if(k>=l)
return 2;
else
return 3;
}
}
}
int findfew()
{
int i=0,j=0,k=0,l=0;
i=need[0][0]+need[0][1];
i+=need[0][2];
j=need[1][0]+need[1][1];
j+=need[1][2];
k=need[2][0]+need[2][1];
k+=need[2][2];
l=need[3][0]+need[3][1];
l+=need[3][2];
if(i<=j)
{
if(i<=k)
{
if(i<=l)
return 0;
else
return 3;
}
else
{
if(k<=l)
return 2;
else
return 3;
}
}
else
{
if(j<=k)
{
if(j<=l)
return 1;
else
return 3;
}
else
{
if(k<=l)
return 2;
else
return 3;
}
}
}
int checksafe(int n)
{
int work[3],finish[M],que[M];
int i=0,k=0;
for(i=0;i<M;i++)
finish[i]=false;
for(;;)
{
work[0]=available[0];
work[1]=available[1];
work[2]=available[2];
i=n;
while(i<M)
{
if(finish[i]==false&&need[i][0]<=work[0]&&need[i][1]<=work[1]&&need[i][2]<=work[2])
{
work[0]+=allocation[i][0];
work[1]+=allocation[i][1];
work[2]+=allocation[i][2];
finish[i]=true;
que[k]=i;
k++;
i=0;
}
else
i++;
}
for(i=0;i<M;i++)
if(finish[i]==false)
{
printf("存在死锁!\n");
return 1;
break;
}
break;
}
printf("\n");
printf("检测结果:不存在死锁!\n");
printf("安全序列为:");
for(i=0;i<M;i++)
printf("%d\t",que[i]);
printf("\n");
return 0;
}
void main()
{
int m=0,n=0,i=0,j=0;
printf("\t\t\t死锁的检测与解除\n");
printf("\n");
input();
output();
printf("请输入请求资源的进程号:");
scanf("%d",&n);
printf("\n");
printf("请输入进程%d对3类资源的需求量:",n);
for(j=0;j<3;j++)
scanf("%d",&request[j]);
printf("\n");
change(n);
if(checksafe(n))
{
check:
{
m=findmany();
printf("\n");
printf("撤销进程%d所占用的资源!\n",m);
for(j=0;j<3;j++)
{
available[j]+=allocation[m][j];
need[m][j]+=allocation[m][j];
allocation[m][j]=0;
}
n=findfew();
for(j=0;j<3;j++)
{request[j]=need[n][j]; }
change(n);
if(checksafe(n))
goto check;
}
}
output();
}
六、运行结果
无死锁的输入输出集
有死锁的输入输出集
有连续死锁的输入输出集