银行家算法是一种避免死锁的有效算法,它借鉴了银行家贷款的策略。在分配资源之前,银行家会检查系统是否有足够的资源满足进程的最大需求,若有,则暂时分配资源,然后继续检查剩余资源是否足够满足其他进程的最大需求。只有当所有进程的需求都能得到满足时,才进行资源分配。
代码实现:
#include<stdio.h>
void menu(){
printf("--------------------------------------------\n");
printf("----- 银行家算法 -----\n");
printf("----- 1.判断当前是否安全,输出安全序列 -----\n");
printf("----- 2.提出新的请求,并判断是否安全 -------\n");
printf("----- 0.退出进程调度 -----------------------\n");
printf("--------------------------------------------\n");
}
//将当前系统分配信息打印
void print(int allocation[5][4],int need[5][4],int available[4]){
int i,j;
printf("allocation:\n");
for(i=0;i<5;i++){
printf("P%d|",i);
for(j=0;j<4;j++){
printf(" %d ",allocation[i][j]);
}
printf("\n");
}
printf("\n");
printf("need:\n");
for(i=0;i<5;i++){
printf("P%d|",i);
for(j=0;j<4;j++){
printf(" %d ",need[i][j]);
}
printf("\n");
}
printf("\n");
printf("available:\n");
for(i=0;i<4;i++){
printf(" %d",available[i]);
}
printf("\n");
}
//安全性检测算法
void safe(int work[4],int allocation[5][4],int need[5][4],int finish[5])
{
int link[5]={0};//用来存放安全序列
int i,j,k,m=0,n=5;
int count;
while(n--) //有五个进程,有5次从进程编号0开始找的机会
{
for(i=0;i<5;i++)
{
if(finish[i]==0) //未完成进程i
{
count=0;
for(j=0;j<4;j++) //对进程i提出的资源请求和可用资源进行比较
{
if(need[i][j]<=work[j]&&finish[i]==0)
{
count++;
}
}
/*当count==4时,说明当前进程需要的每一项资源都小于等于可用资源,
可使得该进程完成工作并释放资源*/
if(count==4)
{
for(k=0;k<4;k++)
{
work[k]+=allocation[i][k]; //该进程还回之前已分配的资源
}
link[m++]=i; //将这个进程加入到安全序列中
finish[i]=1; //并将它的完成与否标记为1,代表已经完成
}
}
}
}
//如果m==5,说明所有进程号都被存入link数组中,存在一个安全序列
if(m==5)
{
printf("该状态安全,安全序列是:");
for(i=0;i<m;i++)
{
printf("P%d ",link[i]);
}
printf("\n");
}
else
{
printf("该状态不安全!\n");
}
}
//银行家算法(判断当前是否安全;或某进程提出新的申请后判断是否安全)
void judge_apply(int input){
int i=0,j=0;
int count1=0;
int count2=0;
//根据题目设置好初始值
int allocation[5][4]={{0,0,3,2},
{1,0,0,0},
{1,3,5,4},
{0,3,3,2},
{0,0,1,4}};
//进程有5个,资源有4种
int need[5][4]={{0,0,1,2},
{1,7,5,0},
{2,3,5,6},
{1,6,5,2},
{0,6,5,6}};
//各项资源的可用数量
int available[4]={1,6,2,2};
int finish[5]={0}; //是否该进程已完成,0未完成,1已完成
int request[4]={0};
//打印当前系统资源分配情况
print(allocation, need,available);
//根据用户的选择来执行
if(input==1){
//判断当前状态是否安全
//直接调用安全性算法
safe(available,allocation,need,finish);
}
else{
//某进程提出请求后是否可以满足
printf("提出请求的进程是:");
scanf("%d",&i);
while(1){
if(i<0||i>4){
printf("进程号错误,请重新输入:");
scanf("%d",&i);
}
else
break;
}
printf("请求的资源数分别是:");
for(j=0;j<4;j++){
scanf("%d",&request[j]);
}
//判断申请的资源数是否大于需要的资源数,大于说明错误
for(j=0;j<4;j++){
if(request[j]<=need[i][j]){
count1++;
}
}
if(count1==4){
for(j=0;j<4;j++){
//判断当前可用资源是否大于申请资源
if(request[j]<=available[j]){
count2++;
}
}
if(count2==4){
//有足够的可用资源,进行预分配,调用安全性检测算法
for(j=0;j<4;j++){
available[j]-=request[j];
allocation[i][j]+=request[j];
need[i][j]-=request[j];
}
safe(available,allocation,need,finish);
}
else{
printf("当前系统可用资源少于申请资源,不能分配,需要等待!!!\n");
}
}
else{
printf("进程申请资源大于其需要资源,出错了!!!\n");
return ;
}
}
}
void test() {
int input = 0;
do {
menu();
printf("请选择:->");
scanf("%d", &input);
switch (input)
{
case 1:
judge_apply(input);
break;
case 2:
judge_apply(input);
break;
case 0:
printf("已退出银行家算法\n");
break;
default:
printf("输入有误,请重新输入!\n");
break;
}
} while (input);
}
int main(){
test();
return 0;
}
资源分布图:
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 1 6 2 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
银行家算法的安全验证序列 :
验证步骤:
步骤1:P0
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 1 6 5 4 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤2 P3
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 1 9 8 6 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤3:P4
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 1 9 1 10 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 0 3 3 2 | 1 6 5 2 | |
P4(finish) | 0 0 1 4 | 0 6 5 6 |
步骤4:P1
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 2 9 1 10 |
P1(finish) | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 0 3 3 2 | 1 6 5 2 | |
P4(finish) | 0 0 1 4 | 0 6 5 6 |
步骤5:P2
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 3 12 6 14 |
P1(finish) | 1 0 0 0 | 1 7 5 0 | |
P2(finish) | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 0 3 3 2 | 1 6 5 2 | |
P4(finish) | 0 0 1 4 | 0 6 5 6 |
新的请求(超出目前Need的情况)请求不安全
新的请求(超出目前Available的情况)请求不安全。
提出新的请求(P1 request [1 0 0 0]),请求不安全
资源分配步骤:
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 1 6 2 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤1:P1请求1 0 0 0,小于need值符合请求
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 1 6 2 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤2:允许完成,将请求分配给P1
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 0 6 2 2 |
P1 | 2 0 0 0 | 0 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤3:进行匹配,P0符合要求
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 0 6 2 2 |
P1 | 2 0 0 0 | 0 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤4:分配,返还
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 0 6 5 4 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤5:剩下的P1 P2 P3 P4不满足分配条件,原因是availble资源不足
提出新的请求(P3 request [1 5 1 0]),请求安全:
资源分配图:
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 1 6 2 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 0 3 3 2 | 1 6 5 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤1:对比P3的need参数,判断是否符合分配
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 1 6 2 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 1 8 4 2 | 0 1 4 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤2:满足条件,下发资源
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0 | 0 0 3 2 | 0 0 1 2 | 0 1 1 2 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 1 8 4 2 | 0 1 4 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤3:P0请求资源,分配资源,完成运行,返还资源
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 0 1 4 4 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3 | 1 8 4 2 | 0 1 4 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤4:P3请求资源,分配资源,完成运行,返还资源
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 1 9 8 6 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 1 8 4 2 | 0 1 4 2 | |
P4 | 0 0 1 4 | 0 6 5 6 |
步骤5:P4请求资源,分配资源,完成运行,返还资源
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 1 9 9 10 |
P1 | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 1 8 4 2 | 0 1 4 2 | |
P4(finish) | 0 0 1 4 | 0 6 5 6 |
步骤6:P1请求资源,分配资源,完成运行,返还资源
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 2 9 9 10 |
P1(finish) | 1 0 0 0 | 1 7 5 0 | |
P2 | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 1 8 4 2 | 0 1 4 2 | |
P4(finish) | 0 0 1 4 | 0 6 5 6 |
步骤7:P2请求资源,分配资源,完成运行,返还资源。
资源 进程 | Allocation A B C D | Need A B C D | Available A B C D |
P0(finish) | 0 0 3 2 | 0 0 1 2 | 3 12 14 14 |
P1(finish) | 1 0 0 0 | 1 7 5 0 | |
P2(finish) | 1 3 5 4 | 2 3 5 6 | |
P3(finish) | 1 8 4 2 | 0 1 4 2 | |
P4(finish) | 0 0 1 4 | 0 6 5 6 |