操作系统课程设计之银行家算法

操作系统 同时被 3 个专栏收录
4 篇文章 0 订阅
3 篇文章 0 订阅
2 篇文章 0 订阅

操作系统课程设计之银行家算法

背景

银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。
我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:

  1. 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;

  2. 顾客可以分期贷款,但贷款的总数不能超过最大需求量;

  3. 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;

  4. 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.

    操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。
    银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。安全状态与不安全状态定义如下:
    安全状态
    如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。
    不安全状态
    不存在一个安全序列。不安全状态不一定导致死锁。

问题描述

操作系统程序设计之银行家算法具体要求如下:

  1. 资源种类与数目可在输入框进行设置,在资源分配过程中可以随时增加进程及其对资源的需求;
  2. 可读取样例数据(要求存放在外部文件中)进行资源种类、数目与进程数的初始化;
  3. 在资源分配过程中可以随时进行系统安全状态检测。
  4. 如果能够通过系统安全状态检测,则系统对该进程进行资源分配;当进程满足所有资源分配 后能够自行释放所有资源,退出资源竞争;
  5. 要求进行安全性检查时按指定策略顺序进行,即按每个进程当前 Need 数由小至大进行排序, 如果 Need 数相同,则按序号由小至大进行排序;
  6. 具有一定的数据容错性。

数据结构

资源种类数和进程数
资源种类数表示当前含有资源的种类的数量,符号表示为m;进程数即表示当前待分配资源的进程数量,符号表示为n。
总资源Resource
是个含有m个元素的数组,其中的每一个元素代表一类资源的总数目。如果Available[j]=K,则表示系统中共有Rj类资源K个。
最大需求矩阵Need
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Need[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
分配矩阵Allocation
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。
需求矩阵Request
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。Need计算公式如下:   
Request[i,j]=Need[i,j]-Allocation[i,j]
可利用资源数Available
是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个,计算方法如下:
在这里插入图片描述

算法流程

  1. 初始化算法流程
    初始化算法主要增加了算法的输入检测的冗余性,思想为尽力而为地防止非法输入破坏程序地健壮性,其流程图如下:

在这里插入图片描述2) 银行家算法流程
银行家算法与经典银行家算法大致相同,主要是增强了算法流程的友好性,使用户自主的控制程序的步骤,是否退出等均由使用者决定,算法具体流程如下:
在这里插入图片描述3) 安全检测算法流程图
为了解决上述地安全性检查,其中i的顺序为Request矩阵从小到大的排序(资源数相同则进程编号小的优先)的结果,满足算法指定的搜索策略进行进程遍历,安全性检查算法流程如下:
在这里插入图片描述
4) 整体算法流程
综上,该程序整体流程如下流程图:
在这里插入图片描述

程序源代码

/*
1.资源种类与数目可在输入框进行设置,在资源分配过程中可以随时增加进程及其对资源的需求(已完成)。 
2.可读取样例数据(要求存放在外部文件中)进行资源种类、数目与进程数的初始化。-----已完成 
3.在资源分配过程中可以随时进行系统安全状态检测。------已完成
4.如果能够通过系统安全状态检测,则系统对该进程进行资源分配;当进程满足所有资源分配 后能够自行释放所有资源,退出资源竞争。------已完成 
5.要求进行安全性检查时按指定策略顺序进行,即按每个进程当前 Need 数由小至大进行排序, 如果 Need 数相同,则按
序号从小到大进行排序。----已完成
6.具有一定的数据容错性。-----已完成
*/
#include<stdio.h>   //C语言标准输入输出文件
#include <stdlib.h> //C语言标准库头文件
#define true 1			  //真为1
#define false 0			  //假为0
#define MAXINT 10		  //最大数量


//以下是内置数据定义
#define N 4
#define M 3
int resource[M]={10,5,7};//内置资源资源数据
int available[M]={0};
int need[N][M]= 
{7,5,3,
3,2,2,
9,0,2,
2,2,2};
int allocation[N][M]=
{0,1,0,
2,0,0,
3,0,2,
2,1,1};
int request[N][M]={0};
bool Finish[N];
int temp_series[N]={0};
int safeSeries[N]={0};//用于存放安全序列
int allocation_bak[N][M] =
{0,1,0,
2,0,0,
3,0,2,
2,1,1};
int need_bak[N][M]= 
{7,5,3,
3,2,2,
9,0,2,
2,2,2};
//以下是键盘输入变量
int processNum;//N,进程数量
int resourceNum;//M,资源种数
int input_resource[MAXINT];
int input_available[MAXINT];
int input_need[MAXINT][MAXINT];
int input_allocation[MAXINT][MAXINT];
int input_request[MAXINT][MAXINT]={0};
bool input_Finish[MAXINT]; 
int input_safeSeries[MAXINT]={MAXINT};
int input_temp_series[MAXINT]={0};
//函数声明
void Init(int ack);
void input_showInfo();
void showInfo();
bool isSafe();
bool input_isSafe();
void SafeInfo(int *work, int i);
void input_SafeInfo(int *work, int i);
int input_wheInit();
void bank();
void input_bank();
int checkDataRight();
void bye();
void isContinue();
void ProcessData();
//函数实现
void Init(int ack)//初始化函数,用于键盘输入和文件数据读取
{
	if(ack==1)//键盘输入
	{
		int i, j;
		printf("\n-----------------------------------------------\n\n");
		printf("输入进程数量(1~10):");
		scanf("%d",&processNum);getchar();
		while(true)
		{
			if(processNum>=1&&processNum<=10)//合法输入
			{
				break;
			}
			else//非法输入
			{
				printf("输入错误!请重新输入进程数量(1~10):");
				scanf("%d",&processNum);
				getchar();
			}
		}
		printf("\n输入资源类型数量(1~10):");
		scanf("%d",&resourceNum);getchar();
		while(true)
		{
			if(resourceNum>=1&&resourceNum<=10)
			{
				break;
			}
			else
			{
				printf("输入错误!请重新输入资源类型数量(1~10):");
				scanf("%d",&resourceNum);getchar();
			}
		}
		printf("\n****************输入每种资源的数目****************\n\n");
		for(i = 0; i < resourceNum; i++)
		{
			printf("请输入第%d个资源的数目(0~65535):",i+1);
			scanf("%d",&input_resource[i]);getchar();
			while(true)
			{
				if(input_resource[i]>=0 && input_resource[i]<65535)
				{
					break;
				}
				else
				{
					printf("输入错误!请重新输入第%d个资源的数目(0~65535):",i+1);
					scanf("%d",&input_resource[i]);getchar();
				}

			}
			printf("\n");
		}
		printf("\n****************输入最大需求矩阵****************\n\n");
		for(i = 0; i < processNum; i++)
		{
			for(j = 0; j < resourceNum; j++)
			{
				printf("请输入第%d个进程的第%d种资源的数量(0~65535):",i+1,j+1);
				scanf("%d",&input_need[i][j]);getchar();
				while(true)
				{
					if(input_need[i][j]>=0 && input_need[i][j]<65535)
					{
						break;
					}
					else
					{
						printf("输入错误!请重新第%d个进程的第%d种资源的数量(0~65535)",i+1,j+1);
						scanf("%d",&input_need[i][j]);getchar();
					}
				}
				printf("\n");
			}
		}
		printf("\n****************输入分配矩阵****************\n\n");
		for(i = 0; i < processNum; i++)
		{
			for(j = 0; j < resourceNum; j++)
			{
				printf("请为第%d个进程的第%d种资源分配数量(0~65535):",i+1,j+1);
				scanf("%d",&input_allocation[i][j]);getchar();
				while(true)
				{
					if(input_allocation[i][j]>=0 && input_allocation[i][j]<65535)
					{
						break;
					}
					else
					{
						printf("输入错误!请重新为第%d个进程的第%d种资源分配数量(0~65535):",i+1,j+1);
						scanf("%d",&input_allocation[i][j]);getchar();
					}
				}
				printf("\n");
			}
		}
	   // 计算需求矩阵
		for(i = 0; i < processNum; i++)
		{
			for(j = 0; j < resourceNum; j++)
			{
			   input_request[i][j]=input_need[i][j]-input_allocation[i][j];
			   if(input_request[i][j]<=0)
			   {
					input_request[i][j]=0;
			   }
			}
		}
	}//end of if键盘输入
	else//从文档输入
	{
		 int i,j;
		 FILE *fpRead=fopen("input.txt","r");//读取文件中的内容	
		 if(fpRead==NULL)  
		 {  
			printf("\nSorry.....打开文件失败!:(\n");
			return ;  
		 }
		 //读取进程数量
		 fscanf(fpRead,"%d ",&processNum); 
		 //输入资源类型数量
		 fscanf(fpRead,"%d ",&resourceNum); 
		 //输入每种资源的数目
		 for(i = 0; i < resourceNum; i++)
		 {
			fscanf(fpRead,"%d ",&input_resource[i]);
		 }
		 //输入最大需求矩阵
		 for(i = 0; i < processNum; i++)
		 {
			for(j = 0; j < resourceNum; j++)
			{
				fscanf(fpRead,"%d ",&input_need[i][j]); 
			}
		 }
		//输入分配矩阵
		for(i = 0; i < processNum; i++)
		{
			for(j = 0; j < resourceNum; j++)
			{
				fscanf(fpRead,"%d ",&input_allocation[i][j]); 
			}
		}
		//计算需求矩阵
		for(i = 0; i < processNum; i++)
		{
			for(j = 0; j < resourceNum; j++)
			{
			   input_request[i][j]=input_need[i][j]-input_allocation[i][j];
			}
		}
	}
	if(!checkDataRight())
	{
		printf("\nsorry...程序所读取的文件中数据有错误:(\n");
		exit(1);
	}
}
int checkDataRight()//检查文件中的数据是否正确,错误返回0,反之返回1
{
	int i,j;
	if(processNum>=1&&processNum<=10)
	{
	}
	else
	{
		return 0;	
	}
	if(resourceNum>=1&&resourceNum<=10)
	{
	}
	else
	{
		return 0;
	}
	for(i = 0; i < resourceNum; i++)
	{
		if(input_resource[i]>=0 && input_resource[i]<65535)
		{
		}
		else
		{
			return 0;
		}
	}
	for(i = 0; i < processNum; i++)
	{
		for(j = 0; j < resourceNum; j++)
		{
			if(input_need[i][j]>=0 && input_need[i][j]<65535)
			{
			}
			else
			{
				return 0;
			}
		}
	}
	for(i = 0; i < processNum; i++)
	{
		for(j = 0; j < resourceNum; j++)
		{
			if(input_allocation[i][j]>=0 && input_allocation[i][j]<65535)
			{
			}
			else
			{
				return 0;
			}
		}
	}
	return 1;
}
void input_showInfo()//文件读取和键盘输入的信息展示
{
	int i,j;
	printf("\n---------------------------------------------------------\n");
    printf("当前资源总量:");
    for(j = 0; j <resourceNum; j++)
	{
        printf("%d ",input_resource[j]);
    }
    printf("\n");
	//计算Avaliable向量
	for(i=0;i<resourceNum;i++)
	 {
		 int count=0;
		 for(j=0;j<processNum;j++)
		 {
			 count+=input_allocation[j][i];
		 }
		 input_available[i]=input_resource[i]-count;
	 }
	//计算request向量
	for(i = 0; i < processNum; i++)
	{
        for(j = 0; j < resourceNum; j++)
		{
           input_request[i][j]=input_need[i][j]-input_allocation[i][j];
        }
    }
    printf(" PID\t Need\t\tAllocation\tRequest\n");
    for(i = 0; i < processNum; i++)
	{
        printf(" P%d\t",i);
        for(j = 0; j < resourceNum; j++)
		{
            printf("%d ",input_need[i][j]);
        }
        printf("\t\t");
        for(j = 0; j < resourceNum; j++)
		{
            printf("%d ",input_allocation[i][j]);
        }
        printf("\t\t");
        for(j = 0; j < resourceNum; j++)
		{
			if(input_request[i][j]<=0)
			{
				input_request[i][j]=0;
			}
            printf("%d ",input_request[i][j]);
        }
        printf("\n");
    }
	printf("当前资源剩余:");
    for(j = 0; j < resourceNum; j++){
        printf("%d ",input_available[j]);
    }
	//request排序
	int input_temp_request[MAXINT]={0};

	for(i=0;i<processNum;i++)
	{
		input_temp_series[i]=i;
	}
	for(i = 0; i <processNum; i++)
	{
        for(j = 0; j < resourceNum; j++)
		{
			input_temp_request[i]+=input_request[i][j];
		}
	}
	//冒泡排序算法,根据request进行比较,总和小的优先,总和一样序号小的优先
	for(i=0;i<processNum-1;i++)
	{
		for(j=0;j<processNum-1;j++)
		{
			if(input_temp_request[j]>input_temp_request[j+1])
			{
				//交换序号
				int temp = input_temp_request[j];
				input_temp_request[j]=input_temp_request[j+1];
				input_temp_request[j+1]=temp;
				temp = input_temp_series[j];
				input_temp_series[j]=input_temp_series[j+1];
				input_temp_series[j+1]=temp;
			}
		}
	}//获得排序序列
	/*for(i=0;i<processNum;i++)
	{
		printf("\n%d %d\t",input_temp_request[i],input_temp_series[i]);
	}*/
}
void showInfo()//内置数据的展示
{
    int i,j;
	printf("\n---------------------------------------------------------\n");
    printf("当前资源总量:");
    for(j = 0; j < M; j++){
        printf("%d ",resource[j]);
    }
    printf("\n");
	//计算Avaliable向量
	for(i=0;i<M;i++)
	 {
		 int count=0;
		 for(j=0;j<N;j++)
		 {
			 count+=allocation[j][i];
		 }
		 available[i]=resource[i]-count;
	 }
	//计算request向量
	for(i = 0; i < N; i++)
	{
        for(j = 0; j < M; j++)
		{
           request[i][j]=need[i][j]-allocation[i][j];
		   if(request[i][j]<=0)
		   {
				request[i][j]=0;
		   }
        }
    }
	int temp_request[N]={0};

	for(i=0;i<N;i++)
	{
		temp_series[i]=i;
	}
	//request排序
	for(i = 0; i < N; i++)
	{
        for(j = 0; j < M; j++)
		{
			temp_request[i]+=request[i][j];
		}
	}
	for(i=0;i<N-1;i++)
	{
		for(j=0;j<N-1;j++)
		{
			if(temp_request[j]>temp_request[j+1])
			{
				int temp = temp_request[j];
				temp_request[j]=temp_request[j+1];
				temp_request[j+1]=temp;
				temp = temp_series[j];
				temp_series[j]=temp_series[j+1];
				temp_series[j+1]=temp;
			}
		}
	}//获得排序序列
    printf(" \nPID\t Need\t\tAllocation\tRequest\n");
    for(i = 0; i < N; i++)
	{
        printf(" P%d\t",i);
        for(j = 0; j < M; j++)
		{
            printf("%d ",need[i][j]);
        }
        printf("\t\t");
        for(j = 0; j < M; j++)
		{
            printf("%d ",allocation[i][j]);
        }
        printf("\t\t");
        for(j = 0; j < M; j++)
		{
            printf("%d ",request[i][j]);
        }
        printf("\n");
    }
	printf("当前资源剩余:");
    for(j = 0; j < M; j++){
        printf("%d ",available[j]);
    }
}

bool input_isSafe()//键盘输入的安全检查
{
	int i,j,k;
    int trueFinished = 0;
    int work[MAXINT];
	//复制给work向量
    for(i = 0; i < resourceNum; i++)
	{
        work[i]=input_available[i];
    }
	//Finish向量全部置于false
    for(i = 0; i < processNum; i++)
	{
        input_Finish[i]=false;
    }
    i = 0;
    int temp = 0;//临时存放trueFinished的值变量
	int temp0= 0;//临时存放trueFinished的值变量
	int flag = 0;//标志位,初始化为0
    while(trueFinished != processNum)
	{
        int j =0;
        if(input_Finish[i]!= true)
		{
            for(j = 0; j < resourceNum; j++)
			{
                if(input_request[input_temp_series[i]][j] > work[j])//需求的资源数大于可用的,则break
				{
					break;
				}
            }
        }//end of if
        if(j == resourceNum)//如果需求的都小于可用的
		{
            input_Finish[i]=true;//置为true
            input_SafeInfo(work,input_temp_series[i]);//打印该记录
            for(k = 0; k < resourceNum; k++)
			{
                work[k]+=input_allocation[input_temp_series[i]][k];//回收已分配的
            }
            input_safeSeries[trueFinished++] =input_temp_series[i];//存放进安全序列
        }//end of if
        i++;
        if(i >= processNum)//已经全部轮循一遍以上了
        {
        	if(flag==0)//说明还有没有处理到的进程
        	{
				//临时存放该变量的值
        		temp=trueFinished;
        		temp0=trueFinished;        		
			}
            i = i % processNum;//模运算,将i还原         
            if(flag==1)//说明所有的进程都处理完毕
			{
				temp=trueFinished;
				if(temp == temp0)
					break;
				else
            		temp0=temp;
            }        
            flag=1;
        }
        temp = trueFinished;
    }//end of while

    if(trueFinished == processNum)//全部完成的个数等于进程数,则安全
	{
        printf("\n系统安全!\n\n安全序列为:");
        for(i = 0; i < processNum; i++)
		{
            printf("%d ",input_safeSeries[i]);
        }
		printf("\n");
        return true;
    }
	//否则不安全
    printf("\n\n******系统不安全!******\n");
    return false;
}
bool isSafe()//内置数据安全检查
{
	//按照temp_series的顺序检索
    int i,j,k;
    int trueFinished = 0;
    int work[M];
    for(i = 0; i < M; i++)//复制给work向量
	{
        work[i]=available[i];
    }
	//Finish向量全部置于false
    for(i = 0; i < N; i++)
	{
        Finish[i]=false;
    }
    i = 0;
    int temp = 0;//临时存放trueFinished的值变量
	int temp0= 0;//临时存放trueFinished的值变量
	int flag = 0;//标志位,初始化为0
    while(trueFinished != N)
	{
        int j =0;
        if(Finish[i]!= true)
		{
            for(j = 0; j < M; j++)
			{
                if(request[temp_series[i]][j] > work[j])//需求的资源数大于可用的,则break
				{
					break;
				}
            }
        }//end of if
        if(j == M)//如果需求的都小于可用的
		{
            Finish[i]=true;//置为true
            SafeInfo(work,temp_series[i]);//打印该记录
            for(k = 0; k < M; k++)
			{
                work[k]+=allocation[temp_series[i]][k];//回收已分配的
            }
            safeSeries[trueFinished++] = temp_series[i];//存放进安全序列
        }//end of if
        i++;
        if(i >= N)//已经全部轮循一遍以上了
        {
        	if(flag==0)//说明还有没有处理到的进程
        	{
				//临时存放该变量的值
        		temp=trueFinished;
        		temp0=trueFinished;        		
			}
            i = i % N; //模运算,将i还原        
            if(flag==1)//说明所有的进程都处理完毕
			{
				temp=trueFinished;
				if(temp == temp0)
					break;
				else
            		temp0=temp;
            }        
            flag=1;
        }
        temp = trueFinished;
    }//end of while

    if(trueFinished == N)//全部完成的个数等于进程数,则安全
	{
        printf("\n\n系统安全!\n\n安全序列为:");
        for(i = 0; i < N; i++)
		{
            printf("%d ",safeSeries[i]);
        }
		printf("\n\n");
        return true;
    }
	//否则不安全
    printf("\n\n******系统不安全!******\n");
    return false;
}

void input_SafeInfo(int *work, int i)//打印安全检测过程
{
    int j;
    printf(" P%d\t",i);
    for(j = 0; j < resourceNum; j++)
	{
        printf("%d ",work[j]);
    }
    printf("\t\t");
    for(j = 0; j < resourceNum; j++)
	{
        printf("%d ",input_request[i][j]);
    }
    printf("\t ");
    for(j = 0; j < resourceNum; j++)
	{
        printf("%d ",input_allocation[i][j]);
    }
    printf("\t\t");
    for(j = 0; j < resourceNum; j++)
	{
        printf("%d ",input_allocation[i][j]+work[j]);
    }
    printf("\n");
}
void isContinue()
{
		printf("\n****************是否开启新的一次银行家算法******************\n\n");
		printf("     1.是,开启新的\n\n");
		printf("     0.否,退出系统\n\n");
		int isCon;
		printf("      请选择(0 or 1):");
		scanf("%d",&isCon);
		if(isCon==1)
		{
			ProcessData();
		}
		else if(isCon==0)
		{
			bye();
		}
		else
		{
			printf("\n输入错误,找不到该选项:(\n");
			isContinue();
		}
}
void SafeInfo(int *work, int i)
{
    int j;
    printf(" P%d\t",i);
    for(j = 0; j < M; j++)
	{
        printf("%d ",work[j]);
    }
    printf("\t\t");
    for(j = 0; j < M; j++)
	{
        printf("%d ",request[i][j]);
    }
    printf("\t ");
    for(j = 0; j < M; j++)
	{
        printf("%d ",allocation[i][j]);
    }
    printf("\t\t");
    for(j = 0; j < M; j++)
	{
        printf("%d ",allocation[i][j]+work[j]);
    }
    printf("\n");
}
void bye()
{
	printf("\n\n");
	printf("\n\n");
	char heart[11][150]={
"\t\t  _____   _                        _             ",
"\t\t |_   _| | |_     __ _    _ _     | |__    ___     o O O   ",
"\t\t   | |   | ' \\   / _` |  | ' \\    | / /   (_-<    o        ",
"\t\t  _|_|_  |_||_|  \\__,_|  |_||_|   |_\\_\\   /__/_   TS__[O]  ",
"\t\t_|\"\"\"\"\"|_|\"\"\"\"\"|_|\"\"\"\"\"|_|\"\"\"\"\"|_|\"\"\"\"\"|_|\"\"\"\"\"| {======| ",
"\t\t\"`-0-0-\'\"`-0-0-\'\"`-0-0-\'\"`-0-0-\'\"`-0-0-\'\"`-0-0-\'./o--000'  "			
};
		
   int i;
   printf("\n\n");
   for(i=0;i<6;i++)   //逐行打印
   {
	   printf("%s\n",heart[i]);
   }
   exit(0);
}
void designer()
{
        printf("\n\n☆☆☆☆☆☆☆☆★★设计者信息★★☆☆☆☆☆☆☆☆\n\n");
        printf("\	●●	                         ●●\n\n");
        printf("\	●●	姓             ●●\n\n");
        printf("\	●●	                         ●●\n\n");
        printf("\	●●	班级:         ●●\n\n");
        printf("\	●●	                         ●●\n\n");
        printf("\	●●	学号:    ●●\n\n");
        printf("\	●●	                         ●●\n\n");
        printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");
}
int input_wheInit()//数据来源选择函数
{
	int wheInit;
	printf("\n*******************请选择数据来源*******************\n\n");
	printf("     1.从键盘输入数据\n\n");
    printf("     2.从文件读取数据\n\n");
    printf("     3.读取内置数据\n\n");
	printf("     0.退出系统\n\n");
	printf("      请选择(0-3):");
	while(true)
	{
		if(!scanf("%d",&wheInit))
		{
			printf("\n****************EEROR!输入错误!请重新选择数据来源****************\n\n");
			printf("     1.从键盘输入数据\n\n");
			printf("     2.从文件读取数据\n\n");
			printf("     3.读取内置数据\n\n");
			printf("     0.退出系统\n\n");
			printf("      请选择(0-3):");
			while(getchar()!='\n');
			getchar();
			input_wheInit();
		}
		else if(wheInit>=0&&wheInit<=3)
		{
			if(wheInit==1)// 1.从键盘输入数据
			{
				Init(wheInit);
				return wheInit;
			}
			if(wheInit==2)//2.从文件读取数据
			{
				Init(wheInit);
				return wheInit;
			}
			if(wheInit==3)//3.读取内置数据
			{
				return wheInit;
			}
				if(wheInit==0)//0.退出系统
			{
				bye();
			}
		}
		else
		{
			printf("\n输入错误,找不到该选项:(\n");
			input_wheInit();
			 
		}		
	}  	
}
void bank()//银行家算法
{
	int j;
	int curProcess;
	showInfo();//打印所有进程的资源需求分配信息
	printf("\n---------------------------------------------------------\n");
	printf("\n系统安全情况分析\n");
	printf(" PID\t Work\t\tRequest\tAllocation\tWork+Allocation\n");
	isSafe();
	while(true)
	{
		printf("\n---------------------------------------------------------\n");
		printf("\n输入要分配的进程(0-%d)[输入999退出此次资源分配]:",N-1);
		scanf("%d",&curProcess);
		if(curProcess==999)//退出此次银行家算法
		{
			isContinue();
		}
		while(true)
		{
			//由于这是内置数据,所以为M
			if(curProcess>=0&&curProcess<=M)
			{
				break;
			}
			if(curProcess==999)
			{
				isContinue();
			}
			else
			{
				//非法输入,打印错误信息,并让其重新输入
				printf("\nERROR!输入错误,找不到该进程!请重新输入!\n\n");
				printf("请重新输入要分配的进程(0-%d)[输入999退出系统]:",N-1);
				scanf("%d",&curProcess);
				getchar();
			}
			printf("\n");
		}
		printf("\n**************输入要分配给进程P%d的资源**************\n\n",curProcess);
		
		for(j = 0; j < M; j++)
		{
			printf("还需第%d种资源的个数:",j+1);
			scanf("%d", &request[curProcess][j]);
			getchar();
			while(true)
			{
				if(request[curProcess][j]>=0 && request[curProcess][j]<=999)
				{
					break;
				}
				else
				{
					//非法输入,打印错误信息,并让其重新输入
					printf("ERROR!非法输入!请重新输入!\n\n");
					printf("还需第%d种资源的个数:",j+1);
					scanf("%d", &request[curProcess][j]);
					getchar();
				}
			}
			printf("\n");
		}
		for(j = 0; j < M; j++)
		{
			
			if(request[curProcess][j] <= need[curProcess][j])
				continue;
			else//如果提出的需求大于自身最大的需求,则报错
			{
				printf("ERROR!\n");
				break;
			}
		}
		if(j == M)//提出的请求是合理的
		{
			for(j = 0; j < M; j++)
			{
				if(request[curProcess][j] <= need[curProcess][j])
					continue;
				else
				{
					printf("资源不足,等待中!\n");
					break;
				}
			}
			if(j == M)//资源都满足
			{
				for(j = 0; j < M; j++)
				{//进行分配
					available[j] -= request[curProcess][j];
					allocation[curProcess][j] += request[curProcess][j];
					need[curProcess][j] -= request[curProcess][j];
				}
				printf("\n系统安全情况分析\n");
				printf(" PID\t Work\t\tRequest\tAllocation\tWork+Allocation\n");
				if(isSafe())
				{
					printf("\n\n分配成功!\n\n");
					showInfo();
				}
				else//不安全则进行回收
				{
					for(j = 0; j < M; j++)
					{
						//回收工作
						available[j] += request[curProcess][j];
						allocation[curProcess][j] -= request[curProcess][j];
						need[curProcess][j] += request[curProcess][j];
					}//for
					printf("\n\n分配失败!\n\n");
					showInfo();
				}//else
			}//if
		}//if
	}//while(true)
}
void input_bank()//手动输入和文件读取数据的银行家算法
{
	int j=0;
	input_showInfo();//打印所有进程的资源需求分配信息
	printf("\n---------------------------------------------------------\n");
	printf("\n系统安全情况分析\n");
	printf(" PID\t Work\t\tRequest\tAllocation\tWork+Allocation\n");
	input_isSafe();
	while(true)
	{
		int curProcess;
		printf("\n---------------------------------------------------------\n");
		printf("\n输入要分配的进程(0-%d)[输入999退出此次资源分配]:",processNum-1);
		scanf("%d",&curProcess);
		if(curProcess==999)//退出此次银行家算法
		{
			isContinue();
		}
		while(true)
		{

			if(curProcess>=0&&curProcess<=processNum-1)
			{//输入合法
				break;
			}
			if(curProcess==999)
			{
				isContinue();
			}
			else
			{
				//非法输入,打印错误信息,并让其重新输入
				printf("\nERROR!输入错误,找不到该进程!请重新输入!\n\n");
				printf("请重新输入要分配的进程(0-%d)[输入999退出系统]:",processNum-1);
				scanf("%d",&curProcess);
				getchar();
			}
		}
		printf("\n**************输入要分配给进程P%d的资源**************\n",curProcess);
		for(j = 0; j <resourceNum; j++)
		{
			printf("\n还需第%d种资源的个数:",j+1);
			scanf("%d", &input_request[curProcess][j]);
			getchar();
			while(true)
			{
				if(input_request[curProcess][j]>=0 && input_request[curProcess][j]<=999)
				{
					break;
				}
				else
				{
					//非法输入,打印错误信息,并让其重新输入
					printf("ERROR!非法输入!请重新输入!\n\n");
					printf("还需第%d种资源的个数:",j+1);
					scanf("%d", &input_request[curProcess][j]);
					getchar();
				}
			}
			printf("\n");
		}
		for(j = 0; j < resourceNum; j++)
		{
			if(input_request[curProcess][j] <= input_need[curProcess][j])
				continue;
			else//如果提出的需求大于自身最大的需求,则报错
			{
				printf("ERROR!\n");
				break;
			}
		}
		if(j == resourceNum)//提出的请求是合理的
		{
			for(j = 0; j < resourceNum; j++)
			{
				if(input_request[curProcess][j] <= input_need[curProcess][j])
					continue;
				else
				{//资源不满足
					printf("\n\n资源不足,等待中!\n");
					break;
				}
			}
			if(j == resourceNum)//资源都满足
			{
				for(j = 0; j < resourceNum; j++)
				{
					//暂时进行分配
					input_available[j] -= input_request[curProcess][j];
					input_allocation[curProcess][j] += input_request[curProcess][j];
					input_need[curProcess][j] -= input_request[curProcess][j];
				}
				printf("\n系统安全情况分析\n");
				printf(" PID\t Work\t\tRequest\tAllocation\tWork+Allocation\n");
				if(input_isSafe())
				{
					printf("\n\n分配成功!\n\n");
					input_showInfo();
				}
				else//不安全则进行回收
				{
					for(j = 0; j < resourceNum; j++)
					{
						//回收工作
						input_available[j] += input_request[curProcess][j];
						input_allocation[curProcess][j] -= input_request[curProcess][j];
						input_need[curProcess][j] += input_request[curProcess][j];
					}//end of for
					printf("\n\n分配失败!\n\n");
					input_showInfo();
				}//end of else
			}//end of if
		}//end of if
	}//end of while(true)
}
void ProcessData()
{
	int i,j,curProcess;
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < M; j++)
		{
			 allocation[i][j]=allocation_bak[i][j];
			 need[i][j]=need_bak[i][j];
		}
	}//reset data
    int wheInit = input_wheInit();
    if(wheInit==3)//内置数据
	{
		bank();
	}//if(wheInit==3)内置数据
	else//其他数据来源
	{
		input_bank();
	}
}
int main()
{
	designer();
    ProcessData();
	return 0;
}

结果展示(部分)

内置数据展示

内置数据银行家算法结果展示如下,T0时刻初始化如下表:
PID Need Allocation Request Resource
P0 7,5,3 0,1,0 7,4,3 10,5,7
P1 3,2,2 2,0,0 1,2,2 Available
P2 9,0,2 3,0,2 6,0,0 3,3,4
P3 2,2,2 2,1,1 0,1,1
T0时刻安全检测结果如下表:
PID Work Request Allocation Work+Allocation
P3 3,3,4 0,1,1 2,1,1 5,4,5
P1 5,4,5 1,2,2 2,0,0 7,4,5
P2 7,4,5 6,0,0 3,0,2 10,4,7
P0 10,4,7 7,4,3 0,1,0 10,5,7
系统安全,安全序列为3->1->2->0.
T1时刻,进程P0提出(2,2,2)请求,安全分析如下表:
PID Work Request Allocation Work+Allocation
P3 1,1,2 0,1,1 2,1,1 3,2,3
P1 3,2,3 1,2,2 2,0,0 5,2,3
P0 5,2,3 2,2,2 2,3,2 7,5,5
P2 7,5,5 6,0,0 3,0,2 10,5,7
系统安全,安全序列为3->1->0->2.
程序结束,实验结果截图如下:
在这里插入图片描述在这里插入图片描述剩下的就自己去运行测试啦,代码程序仅供参考。有问题可联系作者。

  • 1
    点赞
  • 0
    评论
  • 14
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

七.银行家算法程序代码 #include<stdio.h> #include<conio.h> #include<iostream> using namespace std; typedef struct Max1 // 资源的最大需求量 { int m_a; int m_b; int m_c; }Max; typedef struct Allocation1 //已分配的资源数 { int a_a; int a_b; int a_c; }Allocation; typedef struct Need1 //还需要的资源数 { int n_a; int n_b; int n_c; }Need; struct Available1 //可利用的资源量 { int av_a; int av_b; int av_c; } q; struct pr //定义一个结构 { char name; Max max; Allocation allocation; Need need; int finishflag; }p[5]; char na[5]; //******************************************** void init() //读入文件"1.txt" { cout<<"各进程还需要的资源数NEED:"<<endl; FILE *fp; fp=fopen("1.txt","r+"); // 打开文件"1.txt" for(int i=0;i<5;i++) { fscanf(fp,"%c,%d,%d,%d,%d,%d,%d\n",&p[i].name,&p[i].max.m_a,&p[i].max.m_b, &p[i].max.m_c,&p[i].allocation.a_a,&p[i].allocation.a_b,&p[i].allocation.a_c); p[i].need.n_a=p[i].max.m_a-p[i].allocation.a_a; p[i].need.n_b=p[i].max.m_b-p[i].allocation.a_b; p[i].need.n_c=p[i].max.m_c-p[i].allocation.a_c; cout<<p[i].name<<": "<<p[i].need.n_a<<" "<<p[i].need.n_b<<" "<<p[i].need.n_c<<endl; } fclose(fp); //关闭文件 } //*********************************************** int fenpei()//分配资源 { cout<<"Available:"; cout<<q.av_a<<" "<<q.av_b<<" "<<q.av_c<<endl; int finishcnt=0,k=0,count=0; for(int j=0;j<5;j++) p[j].finishflag=0; while(finishcnt<5) { for(int i=0;i<5;i++) { if(p[i].finishflag==0&&q.av_a>=p[i].need.n_a&&q.av_b>=p[i].need.n_b&&q.av_c>=p[i].need.n_c) { q.av_a+=p[i].allocation.a_a; q.av_b+=p[i].allocation.a_b; q.av_c+=p[i].allocation.a_c; p[i].finishflag=1; finishcnt++; na[k++]=p[i].name; break; } } count++;//禁止循环过多 if(count>5)return 0; } return 1; } //**************************************************** int shq() //申请资源 { int m=0,i=0,j=0,k=0; //m为进程号; i,j,k为申请的三类资源数 cout<<"请输入进程号和请求资源的数目!"<<endl; cout<<"如:进程号 资源A B C"<<endl; cout<<" 0 2 0 2"<<endl; cin>>m>>i>>j>>k; if(i<=p[m].need.n_a&&j<=p[m].need.n_b &&k<=p[m].need.n_c) { if(i<=q.av_a&&j<=q.av_b&&k<=q.av_c) { p[m].allocation.a_a+=i; p[m].allocation.a_b+=j; p[m].allocation.a_c+=k; p[m].need.n_a=p[m].max.m_a-p[m].allocation.a_a; p[m].need.n_b=p[m].max.m_b-p[m].allocation.a_b; p[m].need.n_c=p[m].max.m_c-p[m].allocation.a_c; cout<<"各进程还需要的资源数NEED:"<<'\n'; for(int w=0;w<5;w++) cout<<p[w].name<<": "<<p[w].need.n_a<<" "<<p[w].need.n_b <<" "<<p[w].need.n_c<<endl; return 1; } else cout<<"Request>Available让进程"<<m<<"等待......"<<endl; } else cout<<"Request>Need,让进程"<<m<<"等待......"<<endl; return 0; } //******************************************** void main() { int flag; char c; cout<<" /******** 银 行 家 算 法********/ "<<endl; cout<<"确认已经在\"1.txt\"文档中正确输入各进程的有关信息后按回车键"<<endl; getch(); init(); q.av_a=10; //各种资源的数量 q.av_b=5; q.av_c=7; while(flag) { for(int i=0;i<5;i++) { q.av_a-= p[i].allocation.a_a; q.av_b-= p[i].allocation.a_b; q.av_c-= p[i].allocation.a_c; } if(fenpei()) { cout<<"这样配置资源是安全的!"<<endl; cout<<"其安全序列是: "; for(int k=0;k<5;k++) cout<<"-->"<<na[k]; cout<<endl; cout<<"有进程发出Request请求向量吗?(Enter y or Y)"<<endl; cout<<endl; c=getch(); if(c=='y'||c=='Y') { if(shq())continue; else break; } else flag=0; } else {flag=0; cout<<"不安全!!!"<<endl;} } }
设计一个n个并发进程共享m个系统资源的程序以实现银行家算法。要求: 1) 简单的选择界面; 2) 能显示当前系统资源的占用和剩余情况。 3) 为进程分配资源,如果进程要求的资源大于系统剩余的资源,不与分配并且提示分配不成功; 4) 撤销作业,释放资源。 编写和调试一个系统动态分配资源的简单模拟程序,观察死锁产生的条件,并采用适当的算法,有效地防止和避免死锁的发生。 银行家算法分配资源的原则是:系统掌握每个进程对资源的最大需求量,当进程要求申请资源时,系统就测试该进程尚需资源的最大量,如果系统中现存的资源数大于或等于该进程尚需求资源最大量时,就满足进程的当前申请。这样就可以保证至少有一个进程可能得到全部资源而执行到结束,然后归还它所占有的全部资源供其它进程使用。 银行家算法中的数据结构 (1)可利用资源向量Available(一维数组) 是一个含有m个元素,其中的每一个元素代表一类可利用的资源数目,其初值是系统中所配置的该类全部可用资源数目。如果Available[j]=k, 表示系统中现有Rj类资源k个。 (2)最大需求矩阵Max(二维数组) m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max(i,j)=k, 表示进程i需要Rj类资源的最大数目为k。 (3)分配矩阵Allocation(二维数组) m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation(i,j)=k, 表示进程i当前已分得Rj类资源k个。 (4)需求矩阵Need (二维数组) 是一个含有n*m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need(i,j)=k, 表示进程i还需要Rj类资源k个,方能完成其任务。 Need(i,j)= Max(i,j)-Allocation(i,j)
©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值