(1)基本概念
死锁:多个进程在执行过程中,因为竞争资源会造成相互等待的局面。如果没有外力作用,这些进程将永远无法向前推进。此时称系统处于死锁状态或者系统产生了死锁。
安全序列:系统按某种顺序并发进程,并使它们都能达到获得最大资源而顺序完成的序列为安全序列。
安全状态:能找到安全序列的状态称为安全状态,安全状态不会导致死锁。
不安全状态:在当前状态下不存在安全序列,则系统处于不安全状态。
(2)银行家算法
银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要满足多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。
在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其它进程使用资源。如果资源分配不当,就会发生进程循环等待资源,则进程都无法继续执行下去的死锁现象。
当一进程提出资源申请时,银行家算法执行下列步骤以决定是否向其分配资源:
1)检查该进程所需要的资源是否已超过它所宣布的最大值。
2)检查系统当前是否有足够资源满足该进程的请求。
3)系统试探着将资源分配给该进程,得到一个新状态。
4)执行安全性算法,若该新状态是安全的,则分配完成;若新状态是不安全的,则恢复原状态,阻塞该进程。
(3)算法代码
银行家算法中的进程:
包含进程Pi的需求资源数量(也是最大需求资源数量,MAX)
已分配给该进程的资源A(Allocation)
还需要的资源数量N(Need=M-A)
Available为空闲资源数量,即资源池(注意:资源池的剩余资源数量+已分配给所有进程的资源数量=系统中的资源总量)
程序需要的头文件:
#include "stdio.h"
#include "math.h"
程序定义的数组:
ALL_RESOURCE[3] //各种资源的数目总和
MAX[5][3] //M个进程对N类资源最大资源需求量
AVAILABLE[3] //系统可用资源数
ALLOCATION[5][3] //M个进程已经得到N类资源的资源量
NEED[5][3] //M个进程还需要N类资源的资源量
Request[20] //请求资源个数
程序定义的方法:
showdata() //函数showdata,输出资源分配情况
changdata(int k) //分配资源
rstordata(int k) //恢复现场
check(int s) //函数check,检查是否安全
bank() //银行家算法主体
#include "stdio.h"
#include "math.h"
#define FALSE 0
#define TRUE 1
int M=5 ; //总进程数
int N=3 ; //资源种类
int ALL_RESOURCE[3]={10,5,7};//各种资源的数目总和
int MAX[5][3]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}}; //M个进程对N类资源最大资源需求量
int AVAILABLE[3]={4,4,4}; //系统可用资源数
int ALLOCATION[5][3]={{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}}; //M个进程已经得到N类资源的资源量
int NEED[5][3]={{7,4,3},{1,2,2},{6,0,0},{0,1,1},{4,3,1}}; //M个进程还需要N类资源的资源量
int Request[20]; //请求资源个数
void showdata() //函数showdata,输出资源分配情况
{
int i,j;
printf(" 各进程已经得到的资源量(allocation): \n");
printf("\t资源0 \t资源1\t 资源2 \n");
for (i=0;i<M;i++)
{
printf("进程p%d: ",i);
for (j=0;j<N;j++)
printf(" %d\t",ALLOCATION[i][j]);
printf("\n");
}
printf("\n");
printf("各进程还需要的资源量(need): \n");
printf("\t资源0 \t资源1\t 资源2\n");
for (i=0;i<M;i++)
{
printf("进程p%d: ",i);
for (j=0;j<N;j++)
printf(" %d\t",NEED[i][j]);
printf("\n");
}
printf("\n");
}
void changdata(int k) //分配资源
{
int j;
for (j=0;j<N;j++)
{
AVAILABLE[j]=AVAILABLE[j]-Request[j];
ALLOCATION[k][j]=ALLOCATION[k][j]+Request[j];
NEED[k][j]=NEED[k][j]-Request[j];
}
}
void rstordata(int k) //恢复现场
{
int j;
for (j=0;j<N;j++)
{ AVAILABLE[j]=AVAILABLE[j]+Request[j];
ALLOCATION[k][j]=ALLOCATION[k][j]-Request[j];
NEED[k][j]=NEED[k][j]+Request[j];
}
}
int check(int s) //函数check,检查是否安全
{ int WORK,FINISH[10];
int i,j,k=0;
for(i=0;i<M;i++)FINISH[i]=FALSE;
for(j=0;j<N;j++)
{
WORK=AVAILABLE[j];
i=s;
do
{
if(FINISH[i]==FALSE&&NEED[i][j]<=WORK)
{
WORK=WORK+ALLOCATION[i][j];
FINISH[i]=TRUE;
i=0;
}
else
{
i++;
}
}while(i<M);
for(i=0;i<M;i++)
if(FINISH[i]==FALSE)
{
printf("\n您输入有误!请重新输入!\n");
return 1;
}
}
printf("批准请求,资源已分配!\n");
return 0;
}
void bank() //银行家算法主体
{
int i=0,j=0,flag,k=0;
while(k==0)
{
flag=0;
showdata();
i=-1;
while(i<0||i>=M)
{
printf(" 请输入需申请资源的进程号(从P0到P%d,否则重输入!): P",M-1);
scanf("%d",&i);
if(i<0||i>=M)
printf(" 输入的进程号不存在,重新输入!");
}
printf("\n请输入进程P%d申请的资源数:",i);
for (j=0;j<N;j++)
{
printf("\n资源%d:",j);
scanf("%d",&Request[j]);
if(Request[j]>NEED[i][j]) //若请求的资源数大于进程还需要i类资源的资源量j
{
printf("进程P%d申请的资源数大于进程P%d还需要类资源的资源量!\n",i,i,j);
printf("申请不合理,出错!请重新选择!\n");
flag=1; break;
}
if(Request[j]>AVAILABLE[j]) //若请求的资源数大于可用资源数
{
printf("进程P%d申请的资源数大于系统可用%d类资源的资源量!\n",i,j);
printf("申请不合理,出错!请重新选择!\n");
flag=1; break;
}
}
if(flag==0)
{
changdata(i); //调用changdata(i)函数,改变资源数
printf("系统目前各种资源可用的数为(available): \n[");
for (j=0;j<N;j++)
{ printf("%d ",AVAILABLE[j]); }
printf("]\n\n");
if(check(i)) //若系统安全
{
rstordata(i); //调用rstordata(i)函数,恢复资源数
showdata(); //输出资源分配情况
}
else //若系统不安全
showdata(); //输出资源分配情况
}
printf("\n");
printf("是否继续,继续请按0,结束请按1:\t");
scanf("%d",&k);
}
}
int main()
{
int i,j;
printf("各种资源的总数量(all): \n[");
for (j=0;j<N;j++)
{ printf("%d ",ALL_RESOURCE[j]); }
printf("]\n\n");
printf("系统目前各种资源可用的数为(available): \n[");
for (j=0;j<N;j++)
{ printf("%d ",AVAILABLE[j]); }
printf("]\n\n");
printf("进程最大资源需求量(MAX): \n");
for (i=0;i<M;i++)
{
printf("进程P%d ",i);
for(j=0;j<N;j++)
{ printf("%d ",MAX[i][j]);
}
printf("\n");
}
printf("\n");
bank();
}