操作系统——避免死锁的银行家算法

1. 先附上源程序(运行程序前请将注释的文件内容创建名为process_info.txt的文件,并放在代码所在目录下)

#include<iostream>
#include<stdio.h>
using namespace std;
typedef int Status;
/*FilePath路径下文件内容(新创建txt文件并更改FilePath路径) 
--------------------------------------------- 
NUM(PROCESS_AND_RESOURCE)
5 3
AVAILABLE
3 3 2
MAX
7 5 3
3 2 2
9 0 2
2 2 2
4 3 3
ALLOCATION
0 1 0
2 0 0
3 0 2
2 1 1
0 0 2
--------------------------------------------- */
//--------------------------宏定义----------------------------------------- 
#define OTHER_ERROR -1 		//其他请求请求资源失败的原因(这里没有用到) 
#define OVER_NEED 0			//资源需求申请超出最大需求值
#define RES_NOT_ENOUGH 1	//系统无足够资源
#define NOT_SAFE 2			//未通过安全性算法检测 
#define OK 3				//通过安全性算法检测,且无其他错误,请求资源成功
//--------------------------函数声明---------------------------------------- 
void ReadProcessInfo();				//读取进程的所有信息
int SafetyJudge();					//安全性检测算法
int NeedNGWork(int Work[],int row);	//用于比较Need[row,j]和Work[j]
Status Request_BankerALG(int Request [],int x);	//判断能否请求成功_银行家算法
void Display();//进程信息和当前系统资源状态显示
void Request();//模拟进程申请资源的过程,并检测能否成功申请
void showMenu();//菜单显示 
//-----------------------------全局变量--------------------------------------
char FilePath[40]="process_info.txt";	
//进程和系统资源信息文件存储位置 
int Num_Process;	//Num_Process为当前系统的进程数量
int Num_Resource;	//Num_Resource为当前系统可提供的资源种类数量
bool *Finish;		//用于安全性检测算法中进程能否顺利完成 
int *Available,**MAX,**Allocation,**Need,*Work;
int Readed=0;		//用于标志是否成功读取文件
int *Sequence;		//用于存储安全序列 
//---------------------------------------------------------------------------
int main()
{
	int select=0;
	while(select!=-1)
	{
		showMenu();
		cout<<"----->>请输入要进行的操作...(退出请输入-1)"<<endl;
		cin>>select;
		switch(select)
		{
			case 1:
			{
				int yes=0;
				if(Readed)
				{
					cout<<"--->>是否重新读取进程和系统资源信息?(1-是/0-否)"<<endl;
					cin>>yes;
					if(yes)
					{
						ReadProcessInfo();
						Readed=1;
						cout<<"数据已更新!"<<endl;
					}
					else cout<<"已选择继续使用原数据..."<<endl;
				}
				else
				{
					ReadProcessInfo();
					Readed=1;
				}
				break;
			}
			case 2:
			{
				if(!Readed)
				cout<<"进程和系统资源信息尚未读取,请执行操作1!"<<endl;
				else Display();
				break;
			}
			case 3:
			{
				if(!Readed)
				cout<<"进程和系统资源信息尚未读取,请执行操作1!"<<endl;
				else SafetyJudge();
				break;
			}
			case 4:
			{
				if(!Readed)
				cout<<"进程和系统资源信息尚未读取,请执行操作1!"<<endl;
				else Request();
				break;
			}
			default:break;
		}
	}
	return 0;
}
int SafetyJudge()//安全性检测算法
{
	int i,j,k=0;
	Work=new int[Num_Resource];
	for(i=0;i<Num_Resource;i++)
	Work[i]=Available[i];	//以Available[]作为Work[]的初值 
	int FALSE=1;
	for(i=0;i<Num_Process;i++)
		Finish[i]=false;//每调用一次安全性检测算法SafetyJudge,初始化Finish[]为false
	while(1)
	{
		FALSE=1;
		for(i=0;i<Num_Process;i++)
		{
			if(Finish[i]==false&&NeedNGWork(Work,i))//满足条件1和2
			{
				FALSE=0;
				//cout<<i<<" satisfied!"<<endl;
				Sequence[k]=i;//记录安全序列
				k++;
				for(j=0;j<Num_Resource;j++)
				{
					Work[j]=Work[j]+Allocation[i][j];
					Finish[i]=true;
				}
			}
		}
		if(FALSE==1)
			break;
	}
	for(i=0;i<Num_Process;i++)
		if(Finish[i]==false)
			break;
	if(i<Num_Process)
	{
		cout<<"该状态未通过安全性检测"<<endl;
		return 0;
	}
	else 
	{
		cout<<"该状态通过安全性检测,安全序列为:"<<endl;
		cout<<"| ";
		for(i=0;i<Num_Process;i++)
			cout<<"P"<<Sequence[i]<<" ";
		cout<<"|"<<endl;
		return 1;
	}	//所有进程都能够完成则返回1,否则返回0
}
int NeedNGWork(int Work[],int row)//用于比较Need[row,j]和Work[j]
{
	int *need=new int[Num_Resource];
	int i;
	for(i=0;i<Num_Resource;i++)
		need[i]=Need[row][i];
	for(i=0;i<Num_Resource;i++)
		if(need[i]>Work[i])
			break;
	if(i<Num_Resource)
		return 0;
	else return 1;//Need[row,j]<=Work[j]时,返回1,否则返回0
}
Status Request_BankerALG(int Request[],int x)
{//第x个进程提出资源请求Request[],若申请成功则返回1,否则返回-1 
	int i,j;
	
	//---------------为初始数组分配空间-------------------------- 
	
	int *Available_init=new int[Num_Resource];
	int **Allocation_init=new int*[Num_Process];
	int **Need_init=new int *[Num_Process];
	for(i=0;i<Num_Process;i++)
	{
		Allocation_init[i]=new int[Num_Resource];
		Need_init[i]=new int[Num_Resource];
	}
	
	//------------------------------------------------------------
	for(i=0;i<Num_Resource;i++)
	Available_init[i]=Available[i];//保存Available[]原始值,在未通过安全性算法时,可将值恢复为原始值
	for(i=0;i<Num_Process;i++)
	{
		for(j=0;j<Num_Resource;j++)
		{
			Need_init[i][j]=Need[i][j];//保存Need[][]原始值,在未通过安全性算法时,可将值恢复为原始值
			Allocation_init[i][j]=Allocation[i][j];//保存Allocation[][]原始值,在未通过安全性算法时,可将值恢复为原始值
		}
	}
	//-----------------------------------------------------------------------------------------------------------------
	
	for(i=0;i<Num_Resource;i++)
	if(Request[i]>Need[x][i])
	return OVER_NEED; //资源需求申请超出最大需求值
	for(i=0;i<Num_Resource;i++)
	if(Request[i]>Available[i])
	return RES_NOT_ENOUGH;	//系统无足够资源
	for(i=0;i<Num_Resource;i++)
	{
		Available[i]-=Request[i];
		Allocation[x][i]+=Request[i];
		Need[x][i]-=Request[i];
	}
	Status Safety=SafetyJudge();
	if(Safety)
	return OK;
	else	//未通过安全性算法,恢复为原始值
	{
		for(i=0;i<Num_Resource;i++)
		Available[i]=Available_init[i];//保存Available[]原始值,在未通过安全性算法时,可将值恢复为原始值
		for(i=0;i<Num_Process;i++)
		{
			for(j=0;j<Num_Resource;j++)
			{
				Need[i][j]=Need_init[i][j];
				Allocation[i][j]=Allocation_init[i][j];
			}
		}
		return NOT_SAFE;
	}
}
void ReadProcessInfo()//读取进程的所有信息 
{
	char temps[50];
	int i,j;
	FILE *fp=fopen(FilePath,"r");
	if(fp==NULL)
	{
		cout<<"文件process_info.txt读取失败!"<<endl;
		exit(-1);
	}
	fscanf(fp,"%s",temps);	//吸收提示字符串
	fscanf(fp,"%d%d",&Num_Process,&Num_Resource);
	fscanf(fp,"%s",temps);	//吸收提示字符串
	
	//----------------------------为需要的所有数组分配空间------------------------------------
	
	Available=new int[Num_Resource];
	MAX=new int*[Num_Process];
	Allocation=new int*[Num_Process];
	Need=new int*[Num_Process];
	Finish=new bool[Num_Process];//为Finsh[]数组分配空间
	Work=new int[Num_Resource];
	Sequence=new int[Num_Process];
	for(i=0;i<Num_Process;i++)
	{
		MAX[i]=new int[Num_Resource];
		Allocation[i]=new int[Num_Resource];
		Need[i]=new int[Num_Resource];
	}
	
	//----------------------------初始化所有数组-------------------------------
	
	for(i=0;i<Num_Resource;i++)
	fscanf(fp,"%d",&Available[i]);
	fscanf(fp,"%s",temps);	//吸收提示字符串
	for(i=0;i<Num_Process;i++)
	for(j=0;j<Num_Resource;j++)
	fscanf(fp,"%d",&MAX[i][j]);
	fscanf(fp,"%s",temps);	//吸收提示字符串
	for(i=0;i<Num_Process;i++)
	for(j=0;j<Num_Resource;j++)
	fscanf(fp,"%d",&Allocation[i][j]);
	
	//-----------------------------计算Need[][]--------------------------------- 
	
	for(i=0;i<Num_Process;i++)
	for(j=0;j<Num_Resource;j++)
	Need[i][j]=MAX[i][j]-Allocation[i][j];
	//--------------------以Available[]作为Work[]的初值 ------------------------
	for(i=0;i<Num_Resource;i++)
	Work[i]=Available[i];	//以Available[]作为Work[]的初值
	cout<<"进程和系统资源信息读取完成!"<<endl;
	fclose(fp);
}
//TODO
void Display()//进程信息和当前系统资源状态显示 
{
	int i,j;
	cout<<"\t-------------------------------"<<endl; 
	cout<<"\t|当前进程数量为"<<Num_Process<<"             |"<<endl;
	cout<<"\t|系统当前可用资源种类数量为"<<Num_Resource<<" |"<<endl;
	cout<<"\t-------------------------------"<<endl;
	cout<<"---------------进程信息和当前系统资源状态---------------"<<endl;
	cout<<"进程\t"<<" Max   "<<"Allocation\t"<<"Need\t"<<"Available"<<endl;
	for(i=0;i<Num_Process;i++)
	{
		cout<<"P"<<i<<"\t";
		for(j=0;j<Num_Resource;j++)
		cout<<MAX[i][j]<<" ";
		cout<<"\t";
		for(j=0;j<Num_Resource;j++)
		cout<<Allocation[i][j]<<" ";
		cout<<"\t\t";
		for(j=0;j<Num_Resource;j++)
		cout<<Need[i][j]<<" ";
		cout<<"\t";
		if(i==0)
		for(j=0;j<Num_Resource;j++)
		cout<<Available[j]<<" ";
		cout<<endl;
	}
	cout<<"--------------------------------------------------------"<<endl;
}
void Request()//模拟进程申请资源的过程,并检测能否成功申请 
{
	int i;
	int x;//申请资源的进程编号 
	int *request=new int[Num_Resource];
	cout<<"请输入申请资源的进程编号"<<endl;
	cin>>x;
	cout<<"--->>请输入进程"<<x<<"申请"<<Num_Resource<<"类资源的数量"<<endl;
	for(i=0;i<Num_Resource;i++)
	cin>>request[i];
	Status result=Request_BankerALG(request,x);
	switch(result)
	{
		case OVER_NEED:cout<<"资源申请失败(失败原因:申请的资源量超出进程当前最大需求量!)"<<endl;break;
		case RES_NOT_ENOUGH:cout<<"资源申请失败(失败原因:申请的资源量超出系统当前剩余资源量!)"<<endl;break;
		case NOT_SAFE:cout<<"资源申请失败(失败原因:申请后的状态不安全,可能存在进程死锁,无法完成资源申请!)"<<endl;break;
		case OK:cout<<"进程"<<x<<"申请资源成功!"<<endl;break;
		default:break;
	}
}
void showMenu()//菜单显示 
{
	cout<<"\t\t|---------------------------------------------------------------|"<<endl;
	cout<<"\t\t|\t\t\t2018年6月29日\t\t                        |"<<endl;
	cout<<"\t\t|\t姓名:赵文浩	学号:16111204082                         |"<<endl;
	cout<<"\t\t|----------------------------MENU-------------------------------|"<<endl;
	cout<<"\t\t|\t1. 读取进程和系统资源信息                               |"<<endl;
	cout<<"\t\t|\t2. 更新并显示进程和系统资源当前状态                     |"<<endl;
	cout<<"\t\t|\t3. 检测当前状态是否安全                                 |"<<endl;
	cout<<"\t\t|\t4. 进程请求资源(避免死锁)-银行家算法                  |"<<endl;
	cout<<"\t\t|---------------------------------------------------------------|"<<endl;
}

2. 结果截图








  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【实验目的】 1. 理解死锁的概念; 2. 用高级语言编写和调试一个银行家算法程序,以加深对死锁的理解。 【实验准备】 1. 产生死锁的原因  竞争资源引起的死锁  进程推进顺序不当引起死锁 2.产生死锁的必要条件  互斥条件  请求和保持条件  不剥夺条件  环路等待条件 3.处理死锁的基本方法  预防死锁避免死锁  检测死锁  解除死锁 【实验内容】 1. 实验原理 银行家算法是从当前状态出发,逐个按安全序列检查各客户中谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户。如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。与预防死锁的几种方法相比较,限制条件少,资源利用程度提高了。缺点:该算法要求客户数保持固定不变,这在多道程序系统中是难以做到的;该算法保证所有客户在有限的时间内得到满足,但实时客户要求快速响应,所以要考虑这个因素;由于要寻找一个安全序列,实际上增加了系统的开销.Banker algorithm 最重要的一点是:保证操作系统的安全状态!这也是操作系统判断是否分配给一个进程资源的标准!那什么是安全状态?举个小例子,进程P 需要申请8个资源(假设都是一样的),已经申请了5个资源,还差3个资源。若这个时候操作系统还剩下2个资源。很显然,这个时候操作系统无论如何都不能再分配资源给进程P了,因为即使全部给了他也不够,还很可能会造成死锁。若这个时候操作系统还有3个资源,无论P这一次申请几个资源操作系统都可以满足他,因为操作系统可以保证P不死锁,只要他不把剩余的资源分配给别人,进程P就一定能顺利完成任务。 2.实验题目 设计五个进程{P0,P1,P2,P3,P4}共享三资源{A,B,C}的系统,{A,B,C}的资源数量分别为10,5,7。进程可动态地申请资源和释放资源系统按各进程的申请动态地分配资源。要求程序具有显示和打印各进程的某一时刻的资源分配表和安全序列;显示和打印各进程依次要求申请的资源号以及为某进程分配资源后的有关资源数据。 3.算法描述 我们引入了两个向量:Resourse(资源总量)、Available(剩余资源量) 以及两个矩阵:Claim(每个进程的最大需求量)、Allocation(已为每个进程分配的数量)。它们共同构成了任一时刻系统资源的分配状态。 向量模型: R1 R2 R3 矩阵模型: R1 R2 P1 P2 P3 这里,我们设置另外一个矩阵:各个进程尚需资源量(Need),可以看出 Need = Claim – Allocation(每个进程的最大需求量-剩余资源量) 因此,我们可以这样描述银行家算法: 设Request[i]是进程Pi的请求向量。如果Request[i , j]=k,表示Pi需k个Rj资源。当Pi发出资源请求后,系统按下述步骤进行检查: (1) if (Request[i]<=Need[i]) goto (2); else error(“over request”); (2) if (Request[i]<=Available[i]) goto (3); else wait(); (3) 系统试探性把要求资源分给Pi(似回溯算法)。并根据分配修改下面数据结构中的值。 剩余资源量:Available[i] = Available[i] – Request[i] ; 已为每个进程分配的数量: Allocation[i] = Allocation[i] + Request[i]; 各个进程尚需资源量:Need[i] = Need[i]-Request[i]; (4) 系统执行安全性检查,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程以完成此次分配;若不安全,试探方案作废,恢复原资源分配表,让进程Pi等待。 系统所执行的安全性检查算法可描述如下: 设置两个向量:Free、Finish 工作向量Free是一个横向量,表示系统可提供给进程继续运行所需要的各资源数目,它含有的元素个数等于资源数。执行安全算法开始时,Free = Available .标记向量Finish是一个纵向量,表示进程在此次检查中中是否被满足,使之运行完成,开始时对当前未满足的进程做Finish[i] = false;当有足够资源分配给进程(Need[i]<=Free)时,Finish[i]=true,Pi完成,并释放资源。 (1)从进程集中找一个能满足下述条件的进程Pi ① Finish[i] == false(未定) ② Need[i] D->B->A A 1 6 B 1 5 C 2 4 D 4 7 Available = (2) ; Resourse = (10) ; 测试结果如下 process number:5 resource number:4 resource series:6 3 4 2 assined matrix:p0:3 0 1 1 p1:0 1 0 0 p2:1 1 1 0 p3:1 1 0 1 p4:0 0 0 0 needed matrix: p0:1 1 0 0 p1:0 1 1 2 p2:3 1 0 0 p3:0 0 1 0 p4:2 1 1 0 p3-->p4-->p0-->p2-->p1 p3-->p4-->p0-->p1-->p2 p3-->p0-->p4-->p2-->p1 p3-->p0-->p4-->p1-->p2 p3-->p0-->p2-->p4-->p1 p3-->p0-->p2-->p1-->p4 p3-->p0-->p1-->p4-->p2 p3-->p0-->p1-->p2-->p4 it is safe,and it has 8 solutions
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值