操作系统--银行家算法(c++)

需求分析

银行家算法是一种最具有代表性的避免死锁的算法。
要解释银行家算法,必须先解释操作系统的安全状态和不安全状态。
所谓安全状态,是指系统能按照某种进程顺序{P1,P2,…,Pn}(称{P1,P2,…,Pn }序列为安全序列),来为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可以顺利完成。安全状态一定没有死锁发生。
如果系统无法找到这样一个安全序列,则称系统处于不安全状态

  • 如果对每一个进程Pi(1<i<n),它以后尚需要的资源量不超过系统当前可利用的资源量与所有的进程Pj(j<n)所占有的资源量之和,则称此进程序列{P1,P2,…-,Pn}是安全的,称作安全序列。

银行家算法

我们可以把操作系统看做是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求资源相当于客户向银行家贷款。

操作系统按银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程尚需求的资源量,若是系统现存的资源可以满足它尚需求的资源量,则按当前的申请量来分配资源,否则就推迟分配。

当进程在执行中继续申请资源时,先测试该进程申请的资源量是否超过了它尚需的资源量。若超过则拒绝分配,若没有超过则再测试系统尚存的资源是否满足该进程尚需的资源量,若满足即可按当前的申请量来分配,若不满足亦推迟分配。

:银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。

基本要求

(1)可以输入某系统的资源以及T0时刻进程对资源的占用及需求情况的表项,以及T0时刻系统的可利用资源数。

(2)对T0时刻的进行安全性检测,即检测在T0时刻该状态是否安全。

(3)进程申请资源,用银行家算法对其进行检测,分为以下三种情况:
A.所申请的资源大于其所需资源,提示分配不合理不予分配并返回。
B.所申请的资源未大于其所需资源,但大于系统此时的可利用资源,提示分配不合理不予分配并返回。
C.所申请的资源未大于其所需资源,亦未大于系统此时的可利用资源,预分配并进行安全性检查:

  • a.预分配后系统是安全的,将该进程所申请的资源予以实际分配并打印后返回。
  • b.与分配后系统进入不安全状态,提示系统不安全并返回。

(4)对输入进行检查,即若输入不符合条件,应当报错并返回重新输入。

目的

在该部分中根据设计题目的要求,充分地分析和理解问题,叙述系统的功能要求,明确问题要求做什么,以及限制条件是什么。

概要设计

算法思路

先对用户提出的请求进行合法性检查,即检查请求是否大于需要的,是否大于可利用的。若请求合法,则进行预分配,对分配后的状态调用安全性算法进行检查。若安全,则分配;若不安全,则拒绝申请,恢复到原来的状态,拒绝申请。

银行家算法步骤

(1)如果Requesti<or=Need,则转向步骤(⑵);否则,认为出错,因为它所需要的资源数已超过它所宣布的最大值。
(2)如果Request<or=Available,则转向步骤(3);否则,表示系统中尚无足够的资源,进程必须等待。
(3)系统试探把要求的资源分配给进程Pi,并修改下面数据结构中的数值:
Available=Available-Request[i];
A1location=Allocation+Request;Need=Need-Request;
(4)系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。

安全性算法步骤

(1)设置两个向量
①工作向量Work。它表示系统可提供进程继续运行所需要的各类资源数目,执行安全算法开始时,Work=Allocation;
②布尔向量Finish。它表示系统是否有足够的资源分配给进程,使之运行完成,开始时先做Finish[i]=false,当有足够资源分配给进程时,令Finish[i]=true.
(2)从进程集合中找到一个能满足下述条件的进程:
①Finish[i]=false
②Need<or=Work
如找到,执行步骤(3)﹔否则,执行步骤(4)。
(3)当进程Р获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work=Work+Allocation;
Finish[i]=true;
转向步骤(2)。
(4)如果所有进程的Finish[i]=true,则表示系统处于安全状态;否则,系统处于不安全状态。

说明本程序中用到的所有抽象数据类型的定义。主程序的流程以及各程序模块之间的层次(调用)关系。

数据结构

最大需求矩阵Max[][]
已分配矩阵Allocation[][]
仍需求矩阵Need[][]=Max[][]-Allocation[][]
可利用资源向量Available[]
申请各类资源向量Request[]
工作向量work[],Finish[]

程序模块

Public static void main(string[] args) //系统主函数
Public void printFrame() //初始化
Public void print() //打印输出
Public void Safty() //利用安全性算法进行安全性检测
Public void changdata(init i) //进行资源分配
Void judge () //利用银行家算法对申请资源进行判定

各模块之间的调用关系

主函数void main()
调用:printFrame(),print(),Safty(),judge()
安全性检测函数Safty()
调用:print()
银行家算法函数judge()
调用:print(),Safty(),和judge()本身

详细设计

主要函数:

1.进行初始化输入的函数
2.打印输出的函数
3.利用安全性算法进行检测的函数
4.进行资源分配的函数
5.利用银行家算法进行判定的函数

程序流程图

程序主要过程流程图:

在这里插入图片描述

银行家算法流程图:

在这里插入图片描述

安全性算法流程图:

在这里插入图片描述

测试

假定系统中有五个进程{P0、P1、P2、P3、P4}和三种类型资源{a、b、c},每一种资源的数量分别为10、5、7。各进程的最大需求、T0时刻资源分配情况如下所示。在这里插入图片描述

开始界面

在这里插入图片描述

初始化并打印输出

在这里插入图片描述
在这里插入图片描述

设计测试用例

测试用例1

进程1发出请求Request(1,0,2),Available(3,3,2)——可以分配
在这里插入图片描述

测试用例2

进程1发出请求Request(1,2,1),Need(0,2,0),Request>Need ——分配不合理,不可以分配
在这里插入图片描述

测试用例3

进程1发出请求Request(3,3,3),Available(2,3,0),Request>Available ——资源不够,不可以分配
在这里插入图片描述

附录:源代码

#include<stdio.h>
#include<stdlib.h>

#define False 0
#define True 1

/********主要数据结构********/
char NAME[100]={0};//资源的名称
int Max[100][100]={0};//最大需求矩阵
int Allocation[100][100]={0};//系统已分配矩阵
int Need[100][100]={0};//还需要资源矩阵
int Available[100]={0};//可用资源矩阵
int Request[100]={0};//请求资源向量	
int Work[100]={0};//存放系统可提供资源量 
int Finish[100]={0}; //标记系统是否有足够的资源分配给各个进程 
int Security[100]={0};//存放安全序列

int M=100;//进程的最大数
int N=100;//资源的最大数

/********初始化数据:输入进程数量、资源种类、各种资源可利用数量、
各进程对资源最大需求量、各进程的资源已分配数量等。********/
void init()
{
	/* m为进程个数,即矩阵行数,n为资源种类,即矩阵列数。*/
    int i,j,m,n;
	int number,flag;
	char name;//输入资源名称
	int temp[100]={0};//统计已经分配的资源
	//输入系统资源数目及各资源初试个数 
	printf("系统可用资源种类为:");
	scanf("%d",&n);
	N=n;
	for(i=0;i<n;i++)
	{
		printf("资源%d的名称:",i);
		fflush(stdin);  //清空输入流缓冲区的字符,注意必须引入#include<stdlib.h>头文件
		scanf("%c",&name);
		NAME[i]=name;
		printf("资源%c的初始个数为:",name);	
		scanf("%d",&number);
		Available[i]=number;
	}
	
	//输入进程数及各进程的最大需求矩阵 
	printf("\n请输入进程的数量:");	
	scanf("%d",&m);
	M=m;
	printf("请输入各进程的最大需求矩阵的值[Max]:\n");
	do{
		flag = False;
		for(i=0;i<M;i++)
			for(j=0;j<N;j++)
			{
				scanf("%d",&Max[i][j]);
				if(Max[i][j]>Available[j])
					flag = True;				
			}
		if(flag)
			printf("资源最大需求量大于系统中资源最大量,请重新输入!\n");								
	} while(flag);
	
			
	//输入各进程已经分配的资源量,并求得还需要的资源量 
	do{
		flag=False;
		printf("请输入各进程已经分配的资源量[Allocation]:\n");
		for(i=0;i<M;i++)
		{
			for(j=0;j<N;j++)
		  	{
				scanf("%d",&Allocation[i][j]);
				if(Allocation[i][j]>Max[i][j])  
					flag=True;				
				Need[i][j]=Max[i][j]-Allocation[i][j];
				temp[j]+=Allocation[i][j];//统计已经分配给进程的资源数目
		  	}
		}
		if(flag)
			printf("分配的资源大于最大量,请重新输入!\n");		
	}while(flag);
	
	//求得系统中可利用的资源量 
	for(j=0;j<N;j++)
		Available[j]=Available[j]-temp[j];
}

/********显示资源分配矩阵********/
void showdata()
{
	int i,j;
	printf("*************************************************************\n");
	printf("系统目前可用的资源[Available]:\n");
	for(i=0;i<N;i++)
        printf("%c  ",NAME[i]);
	printf("\n");
	for(j=0;j<N;j++)
        printf("%d  ",Available[j]);
	printf("\n");
	printf("系统当前的资源分配情况如下:\n");
	printf("            Max   	 Allocation    Need\n");
	printf("进程名     ");
	//输出与进程名同行的资源名,Max、Allocation、Need下分别对应 
	for(j=0;j<3;j++){
		for(i=0;i<N;i++)
			printf("%c  ",NAME[i]);
		printf("     ");
	}
	printf("\n");
	//输出每个进程的Max、Allocation、Need 
	for(i=0;i<M;i++){
		printf(" P%d        ",i);
	    for(j=0;j<N;j++)
			printf("%d  ",Max[i][j]);
		printf("     "); 
		for(j=0;j<N;j++)
			printf("%d  ",Allocation[i][j]);
		printf("     "); 
		for(j=0;j<N;j++)
			printf("%d  ",Need[i][j]);
		printf("\n");
	}
}

/********尝试分配资源********/
int test(int i) //试探性的将资源分配给第i个进程 
{ 
	for(int j=0;j<N;j++)
	{
		Available[j]=Available[j]-Request[j];
		Allocation[i][j]=Allocation[i][j]+Request[j];
		Need[i][j]=Need[i][j]-Request[j];
	}
	return True;
}

/********试探性分配资源作废********/
int Retest(int i) //与test操作相反 
{ 
	for(int j=0; j<N; j++)
	{
		Available[j] = Available[j] + Request[j];
		Allocation[i][j] = Allocation[i][j] - Request[j];
		Need[i][j] = Need[i][j] + Request[j];
	}
	return True;
}

/********安全性算法********/
int safe()
{
	int i,j,k=0,m,apply;
	//初始化work 
	for(j=0;j<N;j++)
        Work[j] = Available[j];
    //初始化Finish 
    for(i=0;i<M;i++) 
    	Finish[i] = False;
	//求安全序列 
	for(i=0;i<M;i++){ 
		apply=0;
		for(j=0;j<N;j++){
			if(Finish[i]==False && Need[i][j]<=Work[j])
			{   
				apply++;
				//直到每类资源尚需数都小于系统可利用资源数才可分配
				if(apply==N)
				{  
					for(m=0;m<N;m++)
				        Work[m]=Work[m]+Allocation[i][m];//更改当前可分配资源
					Finish[i]=True;
					Security[k++]=i;
					i=-1; //保证每次查询均从第一个进程开始		
				}
			}
		}
	}
	
	for(i=0;i<M;i++){
		if(Finish[i]==False){
			printf("系统不安全\n");//不成功系统不安全
			return False;
		}
	}
    printf("系统是安全的!\n");//如果安全,输出成功
    printf("存在一个安全序列:");
	for(i=0;i<M;i++){//输出运行进程数组
		printf("P%d",Security[i]);
		if(i<M-1) 
			printf("->");
	}
	printf("\n");
	return True;
}

/********利用银行家算法对申请资源进行试分********/
void bank()
{
	int flag = True;//标志变量,判断能否进入银行家算法的下一步 
	int i,j;

	printf("请输入请求分配资源的进程号(0-%d):",M-1); 
    scanf("%d",&i);//输入须申请资源的进程号
    
	printf("请输入进程P%d要申请的资源个数:\n",i);
	for(j=0;j<N;j++)
	{
		printf("%c:",NAME[j]);
		scanf("%d",&Request[j]);//输入需要申请的资源
	}
	
	//判断银行家算法的前两条件是否成立 
    for (j=0;j<N;j++)
	{
		if(Request[j]>Need[i][j])//判断申请是否大于需求,若大于则出错
		{ 
			printf("进程P%d申请的资源大于它需要的资源",i);
			printf("分配不合理,不予分配!\n");
			flag = False;
			break;
		}
		else 
		{
            if(Request[j]>Available[j])//判断申请是否大于当前可分配资源,若大于则出错
			{                         
				printf("进程%d申请的资源大于系统现在可利用的资源",i);
				printf("\n");
				printf("系统尚无足够资源,不予分配!\n");
				flag = False;
				break;
			}
		}
    }
    //前两个条件成立,试分配资源,寻找安全序列 
    if(flag) {
		test(i); //根据进程需求量,试分配资源 
		showdata(); //根据进程需求量,显示试分配后的资源量 
		if(!safe()) //寻找安全序列
		{
			Retest(i);
			showdata();
		}
    }
}


int main()//主函数
{	
	char choice;
	printf("\t---------------------------------------------------\n");
	printf("\t||                                               ||\n");
	printf("\t||               银行家算法的实现                ||\n");
	printf("\t||                                               ||\n");
	printf("\t---------------------------------------------------\n");
	init();//初始化数据
    showdata();//显示各种资源
    //用银行家算法判定系统当前时刻是否安全,不安全就不再继续分配资源 
	if(!safe()) exit(0);
	
	do{
		printf("*************************************************************\n");
		printf("\n");
		printf("\n");
		printf("\t-------------------银行家算法演示------------------\n");
		printf("                     R(r):请求分配   \n");	
		printf("                     E(e):退出       \n");
		printf("\t---------------------------------------------------\n");
		printf("请选择:");
		fflush(stdin);  //清空输入流缓冲区的字符,注意必须引入#include<stdlib.h>头文件
		scanf("%c",&choice);
		switch(choice)
		{
			case 'r':
			case 'R':
				bank();break;			
			case 'e':
			case 'E':
				exit(0);
			default: printf("请正确选择!\n");break;
		}
	} while(choice);
}
  • 38
    点赞
  • 246
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件程序媛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值