解析银行家算法
#include <stdio.h>
#define R 5 //进程数目
#define C 3 //资源种类 A,B,C
int flag=0;//0没有执行完,1执行完
int Finish[R]={0};
//可用资源数A B C
int WA[3]={17,5,20};
int wa[3]={17,5,20};//存储初值
//最大需求数
int max[R][C]={{5,5,9},{5,3,6},{4,0,11},{4,2,5},{4,2,4}};
//已分配资源数
int allocation[R][C]={{2,1,2},{4,0,2},{4,0,5},{2,0,4},{3,1,4}};
//还需要资源数
int need[R][C];
void putData();
void sub();
void showNeed();
void sub(){
int request[3];
int i,j;
//资源数
int a,b,c;
printf("请输入要申请资源的进程号:P");
scanf("%d",&j);
printf("\n请输入申请资源数:");
scanf("%d%d%d",&a,&b,&c);
//判断安全序列
if(j<R){//进程号符合要求
if(need[j][0]>=a && need[j][1]>=b && need[j][2]>=c){
if(a>w[0] || b>w[1] || c>w[2]){
printf("请求的资源超出现有资源!!!!!\n请重新输入\n");
sub();
}else{
need[j][0]=need[j][0]-a;
need[j][1]=need[j][1]-b;
need[j][2]=need[j][2]-c;
w[0]-=a;
w[1]-=b;
w[2]-=c;
//判断进程是否进行完毕
if(need[j][0]==0 && need[j][1]==0 && need[j][2]==0){
Flag[j]=1;//标识进程已经结束
w[0]+=max[j][0];
w[1]+=max[j][1];
w[2]+=max[j][2];//统计系统可用资源
safe[p++]=j;
panduan();
}else{
panduan();
}
}
}else if(a>WA[0] || b>WA[1] || c>WA[2]){
printf("输入的资源数超限,请重新输入\n");
sub();
}else{
printf("输入资源超出所需要的资源数,请重新输入\n");
sub();
}
}else{
printf("不存在该进程,请重新输入\n");
sub();
}
}
//循环判断进程能否进行
int n=0;
void panduan(){
for(int i=0;i<R;i++){
if(Flag[i]==0){//判断进程是否进行完毕
if(need[i][0]<=w[0] && need[i][1]<=w[1] && need[i][2]<w[2]){
Flag[i]=1;
w[0]+=max[wait[i]][0];
w[1]+=max[wait[i]][1];
w[2]+=max[wait[i]][2];//统计系统可用资源
safe[p++]=i;
}else{
wait[n++]=i;//需要等待的进程
printf("资源不足,请等待!!\n");
}
}
}
int x=n;//存放等待进程的数量
for(;;){
for(int j=0;j<n;j++){
if(Flag[wait[j]]==0){//判断进程是否进行完毕
if(need[wait[j]][0]<=w[0] && need[wait[j]][1]<=w[1] && need[wait[j]][2]<w[2]){
Flag[wait[j]]=1;
w[0]+=max[wait[j]][0];
w[1]+=max[wait[j]][1];
w[2]+=max[wait[j]][2];//统计系统可用资源
safe[p++]=wait[j];
x--;
}
}
}
//每循环结束进行判断是否还有安全序列
if(x==n){
printf("此时刻不存在安全序列!!!!!!\n");
break;
}else{
printf("此刻存在安全序列!!!!!\n");
for(int k=0;k<R;k++){
printf("P%d\t",safe[k]);
}
printf("\n");
break;
}
}
}
//输出信息
void putData(){
int i,j;
printf("资源种类:A\tB\tC\t\n");
printf("资源数目:%d\t%d\t%d\n",WA[0],WA[1],WA[2]);
//需求资源s数
printf("\n各个进程所需资源数:\n\n");
for(i=0;i<R;i++){
printf("进程P%d:",i);
for(j=0;j<C;j++){
need[i][j]=max[i][j]-allocation[i][j];
printf("%d\t",need[i][j]);
}
printf("\n");
}//进程提交资源申请数目
}
//输出还需要资源数
void showNeed(){
int i,j;
if(flag==1){
printf("剩余可用资源数:A=%d\tB=%d\tC=%d\n",WA[0],WA[1],WA[2]);
wa[0]=WA[0];
wa[1]=WA[1];
wa[2]=WA[2];
}else{
printf("剩余可用资源数:A=%d\tB=%d\tC=%d\n",wa[0],wa[1],wa[2]);
}
printf("\n各个进程所需资源数:\n\n");
for(i=0;i<R;i++){
printf("进程P%d:",i);
for(j=0;j<C;j++){
printf("%d\t",need[i][j]);
}
printf("\n");
}
sub();
}
int main(){
putData();
sub();
}
算法分析
安全状态和不安全状态均指某一时刻的系统状态,,安全状态并不意味着系统不会陷入死锁;不安全状态意味着系统可能会进入死锁,但是不一定,如果在系统的整个运行中一只运用银行家算法保持安全状态,则系统不会陷入死锁,否则在一个时刻存在安全状态是无意义的。可能时刻某个时态从安全状态转变成不安全状态。
此算法最重要的部分就是在申请资源的时刻是否存在安全序列,能否给进程分配资源,一旦不存在安全序列则需要终止本次资源分配,进行存在安全序列的进程分配资源,让每个进程都可以得到资源并且还可以完成进程。
void panduan();方法是判断首次不能进行资源分配的进程,在接下来的资源分配过程中是否可以得到资源,如果循环得不到资源就说明该进程序列不存在安全进程序列。否则就说明该进程序列存在安全序列。
void sub();方法是获取第一次循环时不可以获取资源的序列,其次如果可以获得资源就去判断申请的资源a,b,c和所需要的资源need是否相等,如果相等则说名这个进程是安全的,并且满足了进程所需要的资源,在进程结束后则需要释放资源,这个时候可用资源w增加w+=need,如果没有达到进程需要的资源要求则需要减去申请的资源w-=a,b,c;再次得到可用资源数。
银行计算法基于这样一个原理:如果在系统运行的整个过程中存在一种避免死锁的资源分配方案,则系统就可以顺利推进直至所有进程都进行完毕,反过来,如果进程无法安全进行,则意味着不存在这样一个阻止死锁发生的方案。
如果所有进程的最大资源都小于或者等于系统资源总额,则在银行家算法的作用下,任意时刻都存在安全序列则说明该进程序列时刻都能保持安全状态。深入分析可知:系统的初始状态是安全的那么就说明在这个时刻存在一个安全序列,并且在银行家算法的推进下,这个进程序列可以得到资源并且能继续推进,至少初始状态的安全序列可以将资源合理分配。
如果一个进程在申请了全部可用资源后还无法得到满足,不能及时释放资源,其他进程也无法得到资源,而那个进程一直占用着可用资源,而在这种状态下没有一个可用的安全序列就形成了死锁。但是并不意味着只有一个安全序列,只是利用银行家算法后得到一个最简单的安全序列,更好地利用和分配资源。
关键字:银行家算法、死锁、数据结构