c语言实现银行家算法
基本思想
在避免死锁的方法中,银行家算法是最具代表性的死锁算法。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。在分配资源之前,判断系统是否是安全的;若安全,才分配。
设计思路
1.调用init()函数初始化资源的基本信息(资源的种类数、资源的名字、每种资源的最大个数)和进程的基本信息(进程的个数、每个进程的名字、每个进程对每种资源的最大需求数)。如果输入的进程对资源的最大需求大于资源的最大数,则提示需求超过资源上限,并重新输入。
2.调用init_allocation()函数初始化分配状态,可以输入当前各个进程对各种资源的占有情况,如果输入大于该进程最大需求,则提示当前资源占用超过所需最大资源,并重新输入;如果输入大于资源最大数量,则提示当前资源占用超过资源上限,并重新输入。
3.更新需求矩阵和资源数量
4.输出资源矩阵、最大需求矩阵、已经分配矩阵和仍需分配矩阵。
5.调用allo方法,准备开始分配资源。首先输入进程名和所需各类资源数量,如果进程存在,请求资源数量小于仍需分配的数量,并且请求资源数量小于资源最大数量,则尝试分配,修改分配矩阵、仍需矩阵和资源矩阵,并调用safe方法判断是否安全,安全则分配成功,不安全则重置分配矩阵、仍需矩阵和资源矩阵。本程序尚未处理输入进程不存在的情况。
具体代码
//银行家算法
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//函数声明
void update();
intallo();
//全局变量
int n; //n表示资源的种类数
int m; //m表示进程
//结构体
struct info
{
char name[20];
int claim[50]; //各个进程所需资源的最大需求
int allocation[50];//已经分配
int need[50]; //仍需分配
bool finish; //满足标记
}pro[50];
struct rescource
{
char name[20];
int avaliable;//最大资源数
}resc[50],work[50];
void init()
{
int i,j;
int flag;
printf("请输入资源种类数");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("请输入第%d个资源的名字和最大资源数:\n",i+1);
scanf("%s",&resc[i].name);
scanf("%d",&resc[i].avaliable);
}
printf("请输入进程数:");
scanf("%d",&m);
printf("\n");
for(i=0;i<m;i++)
{
printf("请输入第%d进程的名字和对各资源的最大需求数:\n",i+1);
scanf("%s",&pro[i].name);
pro[i].finish=false;
for(j=0;j<n;j++)
{
scanf("%d",&pro[i].claim[j]);
if(pro[i].claim[j]>resc[j].avaliable)
flag=1;
else
{
pro[i].allocation[j]=0;
pro[i].need[j]=pro[i].claim[j];
flag=0;
}
if(flag==1)
{
i--;
printf("\n需求超过资源上限,请重新输入\n");
}
getchar();
}
}
printf("\n");
}
//初始分配状态
void init_allocation()
{
int i,j;
for (i = 0; i<m; i++)
{
int flag = 0;
printf("\n输入进程%d对当前各个资源占用情况", i + 1);
for (j = 0; j<n; j++)
{
scanf("%d", &pro[i].allocation[j]);
if (pro[i].allocation[j]>resc[j].avaliable) flag = 1;
if (pro[i].allocation[j]>pro[i].claim[j]) flag=2;
}
if (flag == 1)
{
i--;
printf("\n当前资源占用超过资源上限,请重新输入\n");
}
else if(flag==2)
{
i--;
printf("\n当前资源占用超过所需最大资源,请重新输入\n");
}
}
update();
}
//更新需求矩阵need和资源数allocation
void update()
{
int i,j=0;
for (i = 0; i<m; i++)
{
for (j = 0; j<n; j++)
{
pro[i].need[j] = pro[i].claim[j] - pro[i].allocation[j]; //需求资源=最大需求-已经分配
resc[j].avaliable-= pro[i].allocation[j]; //资源最大-=进程已经分配
}
}
}
//绘制矩阵
void print()
{
int i,j=0;
printf("\n******资源矩阵如下******\n");
printf("名称\t数量\t\n");
for (i = 0; i<n; i++)
printf("%s\t%d\t\n", resc[i].name,resc[i].avaliable);
printf("\n******最大需求矩阵******\n");
for(i=0;i<m;i++)
{
printf("进程%s\t",pro[i].name);
for(j=0;j<n;j++)
printf("%d\t",pro[i].claim[j]);
printf("\n");
}
printf("\n******已经分配矩阵******\n");
for(i=0;i<m;i++)
{
printf("进程%s\t",pro[i].name);
for(j=0;j<n;j++)
printf("%d\t",pro[i].allocation[j]);
printf("\n");
}
printf("\n******仍需矩阵******\n");
for(i=0;i<m;i++)
{
printf("进程%s\t",pro[i].name);
for(j=0;j<n;j++)
printf("%d\t",pro[i].need[j]);
printf("\n");
}
printf("\n");
}
intsafe()
{
int i=0,j=0;
int back=1;
for(i=0;i<n;i++)
{
strcpy(work[i].name,resc[i].name);
work[i].avaliable=resc[i].avaliable;
}
printf("正在尝试建立安全队列\n");
for(i=0;i<m;i++)
{
if(pro[i].finish==false)
{
for(j=0;j<n;j++)
{
if(pro[i].need[j]<=work[j].avaliable)
{
work[j].avaliable=work[j].avaliable;
pro[i].finish=true;
}
else
{
pro[i].finish=false;
printf("在进程%s处出现不安全情况,安全队列无法建立",pro[i].name);
break;
}
}
}
}
for(i=0;i<n;i++)
if(pro[i].finish==false)
back=0;
return back;
}
int index(char tname[20])
{
int i=0;
for(i=0;i<m;i++)
{
if(strcmp(pro[i].name,tname)==0)
return i;
}
return -1;
}
//分配函数
int allo()
{
int next;
char temp_pro_name[20]; //临时进程名
struct rescourcetresc[50];
int i=0;
int back_pro=m;
int back=0;
printf("开始分配吗,开始输入1否则输入0");
scanf("%d",&next);
do{
printf("\n请输入进程名,并依次输入所需资源数量\n");
scanf("%s",&temp_pro_name);
for(i=0;i<n;i++)
{
scanf("%d",&tresc[i].avaliable);
}
back_pro=index(temp_pro_name); //返回进程的下标
if(back_pro!=-1)
{
for(i=0;i<n;i++)
{
printf("准备开始为进程%s分配资源\n",pro[back_pro].name);
if(tresc[i].avaliable<=pro[back_pro].need[i])//请求小于等于仍需
{
if(tresc[i].avaliable<=resc[i].avaliable)//请求小于
{
pro[back_pro].allocation[i]=pro[back_pro].allocation[i]+tresc[i].avaliable;
pro[back_pro].need[i]=pro[back_pro].need[i]-tresc[i].avaliable;
resc[i].avaliable=resc[i].avaliable-tresc[i].avaliable;
}
else
{
printf("\n资源%s当前已经不足%d个",resc[i].name,tresc[i].avaliable);
break;
}
}
else
{
printf("进程%s已经不需要%s资源%d个",temp_pro_name,resc[i].name,tresc[i].avaliable);
break;
}
}
}
else
printf("进程尚不存在");
back=safe();
if(back==0)//不安全
{
for(i=0;i<n;i++)
{
pro[back_pro].allocation[i]=pro[back_pro].allocation[i]-tresc[i].avaliable;
pro[back_pro].need[i]=pro[back_pro].need[i]+tresc[i].avaliable;
resc[i].avaliable=resc[i].avaliable+tresc[i].avaliable;
}
printf("\n系统可能会处于不安全状态,本次请求失败");
print();
}
else if(back==1)
{
printf("\n分配成功");
print();
}
}while(next==1);
return 0;
}
//主函数
void main()
{
int i;
init(); //初始化进程和资源的信息
printf("-------------------------------------");
init_allocation();//初始化进程对资源的占用情况
print(); //输出各个矩阵
do
{
printf("选择1--用银行家算法;选择0--退出");
scanf("%d",&i);
if(i==1)
{
allo();
}
}while(i==1);
}
参考结果
1.初始化时输入进程所需资源数大于资源最大数
2.初始化时进程对资源的占用情况大于进程所需
3.初始化时进程对资源的占用大于资源最大可用
4.初始化成功
5.进程请求资源时大于自己仍需资源数
6.分配失败
7.分配成功