admin 管理员组

文章数量: 887021

完成与:2013.12.11左右

1. 算法思想

银行家算法是为了避免死锁的算法,是Dijkstra的银行家算法。由于该算法用于实现银行系统现金贷款的发放而得名的。为实现银行家算法,系统中必须设置若干数据结构。

1) 银行家算法的数据结构

a) 可利用资源向量available

b) 最大需求矩阵

c) 分配矩阵

d) 需求矩阵

2) 银行家算法

Requesti 是进程Pi的请求量,如果Requesti[j]=k,表示进程Pi需要KRj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查。

a) 如果Requesti[j] <=Need[I,j],便转向步骤(b);否则认为出错,因为他所需要的资源数已经超过它所宣布的最大值。

b) 如果Requesi[j] <=Available[j],便转向步骤(c);否则,表示尚无足够的资源,Pi须等待。

c) 系统试探着把资源分配给进程Pi,并修改下面的数据结构中的数值:

Available[j] := Available[j] – Request i[j];

Allocation[i, j] :=Allocation[i, j] + Request i[j];

Need[i, j] := Need[i, j] – Request i[j];

d) 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,已完成本次资源的分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

3) 安全算法

系统所执行的安全算法可描述如下:

(1) 设置两个向量:

 ① 工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work :=Available

② Finish,他表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish := false;当有足够资源分配给进程时,再令Finish[i] :=true

(2) 从进程集合中找到一个满足下述条件的进程:

 ① Finish[i] := false;

 ② Need[i, j] <= Work[j]; 若找到,执行步骤(3),否则,执行步骤(4)

(3) 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给他的资源,故应执行:

Work[j] :=Work[j] + Allocation[i, j];

Finish[i] :=true;

Go to step2;

(4) 如果所有进程的Finish[i] = true 都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

 

 

 

2. 程序代码

#include <stdio.h>
#include <stdlib.h>
#include "head.h"
#include <string.h>
#include <windows.h>

#define PRONUM 80	//进程的最大数目
#define RESNUM 80	//资源的最大数目
#define RESLEN 80	//资源名的最大数目
typedef struct Max_Allocation//进程已分配资源量
{
	char			proName[PRONUM];//进程名
	int				iMax[RESNUM];//最大需求量
	int				iAllocation[RESNUM];//进程已分配资源量
	int				need[RESNUM];//需求量
}Max_Allocation; 
struct course
{
	Max_Allocation	res;//资源需求与分配信息
	int				finish;//是否访问的标志。(0未访问,1已经访问)
};
char	 	 resName[RESNUM][RESLEN];//资源名
int		 work[RESNUM];//可用资源数
int		 request[RESNUM]={0};//请求资源
char	 	 safe_Array[RESNUM][RESLEN];//资源名
int	     available[RESNUM];//可用资源
struct course progress[80]; 
void health_Examination(int proNum, int resNum)
{return; }

///
//此处仅供调试方便
//
void test(){
progress[0].res.iMax[0]=7;
	progress[0].res.iMax[1]=5;
	progress[0].res.iMax[2]=3;
	progress[0].res.iAllocation[0]=0;
	progress[0].res.iAllocation[1]=1;
	progress[0].res.iAllocation[2]=0;

	progress[1].res.iMax[0]=3;
	progress[1].res.iMax[1]=2;
	progress[1].res.iMax[2]=2;
	progress[1].res.iAllocation[0]=2;
	progress[1].res.iAllocation[1]=0;
	progress[1].res.iAllocation[2]=0;

	progress[2].res.iMax[0]=9;
	progress[2].res.iMax[1]=0;
	progress[2].res.iMax[2]=2;
	progress[2].res.iAllocation[0]=3;
	progress[2].res.iAllocation[1]=0;
	progress[2].res.iAllocation[2]=2;

	progress[3].res.iMax[0]=2;
	progress[3].res.iMax[1]=2;
	progress[3].res.iMax[2]=2;
	progress[3].res.iAllocation[0]=2;
	progress[3].res.iAllocation[1]=1;
	progress[3].res.iAllocation[2]=1;

	progress[4].res.iMax[0]=4;
	progress[4].res.iMax[1]=3;
	progress[4].res.iMax[2]=3;
	progress[4].res.iAllocation[0]=0;
	progress[4].res.iAllocation[1]=0;
	progress[4].res.iAllocation[2]=2;

	strcpy(progress[0].res.proName, "P0");
	strcpy(progress[1].res.proName, "P1");
	strcpy(progress[2].res.proName, "P2");
	strcpy(progress[3].res.proName, "P3");
	strcpy(progress[4].res.proName, "P4");

	strcpy(resName[0], "A");
	strcpy(resName[1], "B");
	strcpy(resName[2], "C");
}

void init_Flag(int proNum, int resNum) {
	int i=0;
	for(i=0; i<proNum; i++){
		progress[i].finish=0;//访问标志初始化
	}
	return;
}
void init_Resource(int proNum, int resNum)//初始化资源
{int i=0, j=0;
	for(i=0; i<proNum; i++){
		for(j=0; j<resNum; j++){
			progress[i].res.iMax[j]=0;//最大需求量,初始化为0
			progress[i].res.iAllocation[j]=0;//进程已分配资源量,初始化为0
		}
	}
	return;
}
//初始化需求量
void init_Need(int proNum, int resNum)
{int i=0, j=0;
	for(i=0 ; i<proNum; i++){
		for(j=0 ; j<resNum; j++){
			progress[i].res.need[j]=0;
		}
	}
	return;
}
//初始化可用资源
void init_Available(int resNum) {
int i=0;
	for(i=0; i<resNum; i++){
		available[i]=0;
	}
	return;
}

//输入进程名,资源名,以及进程信息等
void input_info(int proNum, int resNum) {
	int i=0, j=0;
	for(i=0; i<proNum; i++){
		printf("请输入第%d个进程名<共%d>: ", i+1, proNum);
		scanf("%s", progress[i].res.proName);
		for(j=0; j<resNum; j++){
			if(i==0) {
				printf("    请输入第%d个资源类型名<共%d>: ", j+1, resNum);
				scanf("%s", resName[j]);
			}
			printf("        请输入%s类资源的最大需求量: ", resName[j]);
			scanf("%d", &progress[i].res.iMax[j]);
			printf("        请输入%s类资源的当前已分配量: ", resName[j]);
			scanf("%d", &progress[i].res.iAllocation[j]);
			printf(" \n");
		}
		printf(" \n");
	}
	return;
}

//给need赋值
void voluation_Need(int proNum, int resNum) {
	int i=0,j=0;
	for(i=0; i<proNum; i++){
		for(j=0; j<resNum; j++){
			progress[i].res.need[j]=progress[i].res.iMax[j] - progress[i].res.iAllocation[j];
		}
	}
	return;
}
//对可用资源的输入
void input_Available( int resNum) {
	int i=0;
	for(i=0; i<resNum; i++){
		printf("请输入%s类资源的可用数(按回车结束一类资源的输入): ", resName[i]);
		scanf("%d", &available[i]);
		/*
		if( available[i] == 'q' || available[i] == 'Q')//退出检测
		{
			printf("\n\n程序结束。\n");
			exit(0);
		}*/
	}
	return;
}
//初始化work
void init_Work( int resNum) {
	int i=0;
	for(i=0; i<resNum; i++){
		work[i]=*(available+i);
	}
	return;
}
//
//
//以下为整个程序的核心代码
//
///
//此处完成合法性的检查,判断系统是否安全
bool check_safety(int proNum, int resNum) {
	int i=0, j=0, Need=0, countPro=0, countFor=0, countLastPro=0, countFinish=0;//countFor统计循环的次数,countFinish统计已访问的次数
	int num=0;
	while(countPro < proNum ) {
		for(i=0; i<proNum; i++){
			if ( progress[i].finish != 1)//判断该进程是否已经被访问
			{
				for(j=0; j<resNum; j++){
					Need=progress[i].res.iMax[j] - progress[i].res.iAllocation[j]; 
					if( Need <= work[j] ) {continue; }
					else{break; }
				}
				if(j == resNum) {
					for(j=0; j<resNum; j++){
						work[j]=work[j] + progress[i].res.iAllocation[j];//资源拥有量
					}
					strcpy(safe_Array[num++], progress[i].res.proName);
					progress[i].finish=1;//把已访问的进程置1
					countPro++;//统计访问进程的个数
				}
			}
		}
		//以下两个判断都能够满足安全性的检查
		//判断1,效率高
		if(countLastPro == countPro)
		{//判断上一次循环统计的进程个数是否等于本次循环的进程个数,
			//若相等则说明可用资源不能满足当前进程的运行
			return false;
		}
		else{//若相等把这次的进程个数赋给上一次统计的个数
			countLastPro = countPro; }

		//判断2,效率低
		countFor++;//统计循环的次数,若循环次数大于当前进程的个数,则说明可用资源不能满足当前进程的运行
		if(countFor > proNum)//此处proNum加1,是为了防止与countPro相悖
		{return false; }
	}
	return true;
}
//输入请求进程请求名
int input_Request_Name(int proNum) {
	int position=0;
	char reqProName[PRONUM];
	bool flag=true;
	int i=0;
	printf("\n***********************************\n");
	while(flag) {
		printf("按“q”、“Q”结束程序。\n");
		printf("请输入资源请求的进程名:");
		scanf("%s", reqProName);
		if( strcmp(reqProName, "q") ==0 || strcmp(reqProName, "Q") ==0)//退出检测{
			printf("\n\n程序结束。\n");
			exit(0);
		}
		for(i=0; i<proNum; i++){
			if( strcmp(progress[i].res.proName, reqProName)==0 ) {
				position=i;
				flag=false;
				break;
			}
		}
		if( proNum == i)
		{printf("\n您输入的进程不存在。\n");}
	}
	return position;
}
//输入各类资源请求数
bool input_Res_Num(int proNum, int resNum, int *available, int position) {
	bool flag=false;
	int need=0;
	int i=0, iflag=-1;
	//char over; 
	printf("\n*************************************\n");
	printf("请输入资源请求量共%d种。\n", resNum);
	for(i=0; i<resNum; i++){
		printf("请输入第%s类资源请求: ", resName[i]);
		scanf("%d", &request[i]);
		/*if( request[i] == 89)//退出检测
		{
			printf("\n\n程序结束。\n");
			exit(0);
			break;
		}*/
	}
	//此处判断request<=Need 并且 request<=Available
	for(i=0; i<resNum; i++){
		need=progress[position].res.iMax[i] - progress[position].res.iAllocation[i];
		if (request[i] > need  ) {
			printf("资源请求量大于需求资源量,资源不分配\n");
			print_Info(proNum, resNum);//输出信息
			return false;
		}
		if ( request[i] > available[i] ) {
			printf("资源请求量大于可用资源量,资源不分配\n");
			print_Info(proNum, resNum);//输出信息
			return false;
		}
	}
	print_Info(proNum, resNum);//输出信息
	return true; 
}
//请求资源
void request_Resource(int proNum, int resNum, int *available) {
	bool flag=false, allFlag=true;
	int position=0, need=0;
	int i=0; 
	while(!flag) {
		position = input_Request_Name(proNum);//输入资源请求名
		flag = input_Res_Num(proNum, resNum, available, position);
	}
	init_Flag(proNum, resNum);
	init_Work(resNum);//初始化可用资源
	for(i=0; i<resNum; i++){
		progress[position].res.iAllocation[i] += request[i];
		work[i] -= request[i];
	}
	if( check_safety(proNum, resNum) ) {
		for(i=0; i<resNum; i++)//need值改变
		{progress[position].res.need[i] -= request[i]; }
		for(i=0; i<resNum; i++)//available值改变
		{available[i] -= request[i]; }
		printf("安全序列是:\n");
		printf("%s", safe_Array[0]);
		for(i=1; i<proNum; i++)
		{printf("->%s", safe_Array[i]); }
		putchar('\n'); 
		printf("\n此状态安全。\n");
	}
	else{
		printf("\n此状态不安全,资源不分配。\n");
		for(i=0; i<resNum; i++)
		{progress[position].res.iAllocation[i] -= request[i]; }
	}
	return;
}
//格式输出
void print_Info(int proNum, int resNum) {
	int i=0, j=0;
	printf("\n**************************************************************************************************\n");
	printf("********************                操作系统之银行家算法              ****************************\n");
	printf("**************************************************************************************************\n");
	printf("资源情况       Max\t     \t    Allocation\t      \t      Need\t      \t    Available\n");
	printf("进程");
	for(i=0; i<resNum; i++)
	{printf("\t%s", resName[i]); }
	for(i=0; i<resNum; i++)
	{printf("\t%s", resName[i]); }
	for(i=0; i<resNum; i++)
	{printf("\t%s", resName[i]); }
	for(i=0; i<resNum; i++)
	{printf("\t%s", resName[i]); }
	printf("\n\n");
	for(i=0; i<proNum; i++)
	{printf("%s", progress[i].res.proName); 
		for(j=0; j<resNum; j++)
		{printf("\t%d", progress[i].res.iMax[j]); }
		for(j=0; j<resNum; j++)
		{printf("\t%d", progress[i].res.iAllocation[j]); }
		for(j=0; j<resNum; j++)
		{printf("\t%d", progress[i].res.need[j]); }
		for(j=0; j<resNum && i==0; j++)
		{printf("\t%d", available[j]); }
		printf(" \n");
	}
	printf(" \n**************************************************************************************************\n");
	return;
}
//初始化所有需初始化
void init_All(int proNum, int resNum)
	init_Flag(proNum, resNum);//初始化相应的信息
	init_Resource(proNum, resNum);//初始化资源
	init_Need(proNum, resNum);//need初始化
	init_Available(resNum);//初始化可用资源
	test();
	//input_info(proNum, resNum);//输入相应信息
	voluation_Need(proNum, resNum);//给need赋值
	print_Info(proNum, resNum);//输出相应信息
	input_Available(resNum);//可用资源
	init_Work(resNum);//初始化可用资源
}
int main(int argc,char* argv[])
{
	int proNum=5, resNum=3;
	char ch=' ';
	bool is_safe=false;
	int i=0;
	system("title 操作系统之银行家算法  作者:宋腾飞");
	system("mode con cols=100 lines=30 ");//
	while(!is_safe) {
		//printf("请输入进程数及资源数:");
		//scanf("%d%c%d", &proNum, &ch, &resNum); 
		//health_Examination(proNum); 
		init_All(proNum, resNum); 
		if( check_safety(proNum, resNum) )
		{printf("\n此状态安全。\n");
			printf("安全序列是:\n");
			printf("%s", safe_Array[0]);
			for(i=1; i<proNum; i++)
			{printf("->%s", safe_Array[i]); }
			putchar('\n'); 
			is_safe=true; 
			print_Info(proNum, resNum);
		}
		else{
			printf("\n此状态不安全。等待5秒钟后请重新输......\n");
			is_safe=false;
			Sleep(5000);
			//system("cls");
		}
	}
	printf("请等待5秒......\n");
	Sleep(5000); 
	do
	{//system("cls");
		request_Resource(proNum, resNum, available); 
	}while(1); 
	//print_Info(proNum, resNum);//输出相应信息
	return 0;
}

3. 运行结果



本文标签: 银行家 算法 操作系统 代码