操作系统-资源分配银行家算法

资源分配----银行家算法

一、 实验目的
模拟实现银行家算法,用银行家算法实现资源分配和安全性检查。通过本次实验,使学生加深对死锁概念的理解和掌握,并培养学生对操作系统课程的兴趣与高级语言设计的能力。

二、 实验内容 1、要求
设计五个进程{P0···P4}共享三类资源{A,B,C}的系统,每一种资源数量为10,5,7。进程可动态的申请和释放资源,系统按各进程的申请动态地分配资源,在T0时刻的资源分配情况如下表:

Name       Max        Allocation       Need       Available
P0        7,5,3       0,1,0       7,4,3        3,3,2 
P1        3,2,2       2,0,0       1,2,2 
P2        9,0,2       3,0,2       6,0,0
P3        2,2,2       2,1,1       0,1,1
P4        4,3,3       0,0,2       4,3,1

(1) 银行家算法的数据结构
•Resource:一个长度为m向量,表示系统拥有的资源数目。
•Available:一个长度为m向量,表示每类资源的可用数目。
•Max:一个m×n矩阵,定义每个进程的最大资源需求数。
•Allocation:一个m×n矩阵,定义当前分配给每个进程每类资源的数目。
•Need:一个m×n矩阵,表示每个进程还需多少资源。

(2) 实现银行家算法 设:Requesti是进程Pi的请求向量。
当Pi发出资源请求后,系统按如下步骤进行检查:
•如果Request[j] Need[i][j] 则go to 2,否则认为出错。
•如果Request[j] < Available[i][j] 则go to 3,否则表示无足够资源, Pi等待。
•系统进行试探分配,并求该相应数据结构数据
Available:= Available- Requesti
Allocationi:= Allocationi+ Requesti
Needi:= Needi-Requesti
•系统执行安全性算法:安全,把资源分配给Pi,否则, Pi等待。

(3) 实现安全性算法
•设Work 和 Finish是长度分别为m,n的向量
初试值Work =Available ,Finishi = False(所有)
•从进程集合中找到一个能满足下列条件的进程
a. Finishi= False
b. Needi Work 如找到go to 3 否则 go to 4
•当进程Pi 获得资源后,顺利执行,直至完成,并释放分配给它的资源。
Work = Work+ Allocationi
Finishi:= True go to 2
•如果所有进程的Finishi= True 则表示系统安全,否则为不安全。


一、系统安全性检查模块

方案一(不利用goto语句):

//判断系统的安全性
int judSystemSecurity()
{
	int i;
	//更新系统可利用资源量
	for (i = 0; i < resourseType; i++)
	{
		work[i] = available[i];
	}

	int allFinish = 0;
	//把未完成进程置为0
	for (i = 0; i < customerNumber; i++)
	{
		//判断当前进程是否已经完成并且可以回收资源

		//如果已经全部完成
		if (isFinish(i))
		{
			Finish[i] = 1;
			allFinish++;
		}
		else
		{
			Finish[i] = 0;
		}
	}

	int r = 0;//表示当前要判断是否要进行预分配的进程的下标
	int safeIndex = 0;//安全序列的下标
	int temp = 0;//临时变量
	int pNum = 0;//保存临时变量的个数
	//预分配开始,当进程没有全部完成时,一直执行循环
	while (allFinish != customerNumber)
	{
		num = 0;
		//判断是否可以预分配
		for (i = 0; i < resourseType; i++)
		{
			if (need[r][i] <= work[i] && Finish[r] == 0)//判断是否可以预分配
			{
				num++;
			}
		}

		//可以预分配
		if (num == resourseType)
		{
			//输出进程Pr的各项信息
			SafeInfo(work, r);
			//回收资源
			for (i = 0; i < resourseType; i++)
			{
				work[i] = work[i] + allocation[r][i];
			}
			//完成的进程数增加
			allFinish++;
			//保存安全序列
			safeSeries[safeIndex] = r;
			safeIndex++;
			//当前进程安全
			Finish[r] = 1;
		}


		r++;//该式必须在此处	
		if (r >= customerNumber)
		{
			r = r % customerNumber;
			if (temp == allFinish)//temp记录的是上一次循环分配后所有的进程完成数,将上一次进程数跟这次预分配后的进程数
			{					  //进行对比,如果相等,则是不安全的情况,直接break;否则是安全的情况,继续执行
				break;
			}
			temp = allFinish;//更新完成的进程数
		}
		pNum = allFinish;//保存安全序列的个数
	}

	//判断系统是否安全
	for (i = 0; i < customerNumber; i++)
	{
		if (Finish[i] == 0)
		{
			return 0;
		}
	}

	//打印安全序列
	printf("\n安全序列为:");
	for (i = 0; i < customerNumber; i++)
	{
		if (isFinish(i))
		{
			pNum--;
		}
	}
	for (i = 0; i < pNum; i++)
	{
		printf("%d ", safeSeries[i]);
	}
	return 1;
}

方案二(利用goto语句):

//方案二,利用goto语句
int judSystemSecurity_1()
{
	int i, j;
	for (i = 0; i < resourseType; i++)
	{
		work[i] = available[i];
	}
	for (i = 0; i < customerNumber; i++)
	{
		if (isFinish(i))
		{
			Finish[i] = 1;
		}
		else
		{
			Finish[i] = 0;
		}
	}

	int safeIndex = 0;

	NEXT:
	for (i = 0; i < customerNumber; i++)
	{
		if (Finish[i] == 0)
		{
			for (j = 0; j < resourseType; j++)
			{
				if (need[i][j] > work[j])
				{
					break;
				}
			}
			//已完全执行
			if (j == resourseType)
			{
				Finish[i] = 1;
				SafeInfo(work, i);
				safeSeries[safeIndex++] = i;
				//回收资源
				for (j = 0; j < resourseType; j++)
				{
					work[j] += allocation[i][j];
				}
				goto NEXT;
			}
		}
	}

	int pNum = 0;
	for (i = 0; i < customerNumber; i++)
	{
		if (Finish[i] == 0)
		{
			return 0;
		}
		else
		{
			pNum++;
		}
	}
	//打印安全序列
	printf("\n安全序列为:");
	for (i = 0; i < customerNumber; i++)
	{
		if (isFinish(i))//统计没完全执行的进程数
		{
			pNum--;
		}
	}
	for (i = 0; i < pNum; i++)
	{
		printf("%d ", safeSeries[i]);
	}

	return 1;
}

二、资源申请模块:

//判断进程资源请求的安全性
void judRequestSecurity()
{
	//输入预分配的资源编号和各类资源量
	int curProcess;
	printf("请输入预分配资源的进程的编号:");
	scanf("%d", &curProcess);
	getchar();

	int i;
	for (i = 0; i < resourseType; i++)
	{
		printf("请输入给 P%d 预分配的第 %d 类资源量:", curProcess, i + 1);
		scanf("%d", &request[i]);
		getchar();
	}

	//作为安全性的判断变量
	num = 0;
	//进行判断预分配是否合理
	for (i = 0; i < resourseType; i++)
	{
		if (request[i] > need[curProcess][i])
		{
			printf("\n分配错误!请求分配资源量大于所需要的资源量!\n");
			printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
			return;
		}
		else if (request[i] > available[i])
		{
			printf("\n分配错误!请求分配资源量大于可利用资源量!\n");
			printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
			return;
		}
		else
		{
			num++;
		}
	}

	//分配合理,则试探性地分配
	if (num == resourseType)
	{
		num = 0;
		for (i = 0; i < resourseType; i++)
		{
			available[i] -= request[i];
			allocation[curProcess][i] += request[i];
			need[curProcess][i] -= request[i];
			if (need[curProcess][i] == 0)
			{
				num++;
			}
		}
		//分配合理并且此次分配后该进程执行结束,回收资源
		if (num == resourseType)
		{
			for (i = 0; i < resourseType; i++)
			{
				available[i] += allocation[curProcess][i];
			}
			printf("\n进程 P%d 执行完毕,所占用资源全部释放!\n", curProcess);
		}
		else
		{
			printf("\n进程 P%d 未执行完毕,等待\n", curProcess);
		}
	}

	//检查分配后系统是否安全,如果不安全,则收回分配的资源
	printf("\n------------------------------------------------------------------------------------\n");
	printf("当前系统各类资源剩余量:");
	for (int i = 0; i < resourseType; i++)
	{
		printf("%d ", available[i]);
	}

	printf("\n\n当前系统进程状况:\n");
	printf(" Name\t Work\t Need\tAllocation\tWork+Allocation\t Finish\n");
	if (!judSystemSecurity_1())
	{
		for (i = 0; i < resourseType; i++)
		{
			available[i] += request[i];
			allocation[curProcess][i] -= request[i];
			need[curProcess][i] += request[i];
		}
		printf("\n\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT  OBTAIN RESOURCES IMMEDIATELY", curProcess);
	}
	else
	{
		printf("\n\nRESOURCE SECURITY!!!\n\nCUSTOMER P%d CAN OBTAIN RESOURCES IMMEDIATELY", curProcess);
	}
	printf("\n------------------------------------------------------------------------------------\n");
	return;
}

三、完整代码演示:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 

//系统中每种资源的可利用资源数
int available[100] = { 0 };
//进程的最大需求资源数
int max[100][100] = { 0 };
//系统刚开始每个进程已占用资源数
int allocation[100][100] = { 0 };
//每个进程还需要的资源数
int need[100][100] = { 0 };
//判断每个进程是否安全
int Finish[100] = { 0 };
//安全序列号
int safeSeries[100];
//进程请求资源量
int request[100];
//资源计数变量,便于判断安全性
int num;
//系统当前可分配资源量
int work[1000];
//资源种类数和进程数
int resourseType, customerNumber;
//作为是否输入数据的判断变量
int flag = 0;

//函数声明
int isFinish(int row);
void SafeInfo(int* work, int index);
int judSystemSecurity();
int judSystemSecurity_1();
void judRequestSecurity();
void showMenu();
void keyDown();
void InitStastic();


//函数定义
int isFinish(int row)
{
	int j;
	for (j = 0; j < resourseType; j++)
	{
		if (need[row][j] != 0)
		{
			return 0;
		}
	}
	return 1;
}

//进程资源输出
void SafeInfo(int* work, int index)
{
	int j;

	printf(" P%d\t", index);
	for (j = 0; j < resourseType; j++)
	{
		printf("%d ", work[j]);
	}
	printf("\t ");
	for (j = 0; j < resourseType; j++)
	{
		printf("%d ", need[index][j]);
	}
	printf("\t  ");
	for (j = 0; j < resourseType; j++)
	{
		printf("%d ", allocation[index][j]);
	}
	printf("\t  ");
	for (j = 0; j < resourseType; j++)
	{
		printf("%d ", allocation[index][j] + work[j]);
	}
	printf("\t  T");
	printf("\n");

	return;
}

//方案二,利用goto语句
int judSystemSecurity_1()
{
	int i, j;
	for (i = 0; i < resourseType; i++)
	{
		work[i] = available[i];
	}
	for (i = 0; i < customerNumber; i++)
	{
		if (isFinish(i))
		{
			Finish[i] = 1;
		}
		else
		{
			Finish[i] = 0;
		}
	}

	int safeIndex = 0;

	NEXT:
	for (i = 0; i < customerNumber; i++)
	{
		if (Finish[i] == 0)
		{
			for (j = 0; j < resourseType; j++)
			{
				if (need[i][j] > work[j])
				{
					break;
				}
			}
			//已完全执行
			if (j == resourseType)
			{
				Finish[i] = 1;
				SafeInfo(work, i);
				safeSeries[safeIndex++] = i;
				//回收资源
				for (j = 0; j < resourseType; j++)
				{
					work[j] += allocation[i][j];
				}
				goto NEXT;
			}
		}
	}

	int pNum = 0;
	for (i = 0; i < customerNumber; i++)
	{
		if (Finish[i] == 0)
		{
			return 0;
		}
		else
		{
			pNum++;
		}
	}
	//打印安全序列
	printf("\n安全序列为:");
	for (i = 0; i < customerNumber; i++)
	{
		if (isFinish(i))//统计没完全执行的进程数
		{
			pNum--;
		}
	}
	for (i = 0; i < pNum; i++)
	{
		printf("%d ", safeSeries[i]);
	}

	return 1;
}


//判断系统的安全性
int judSystemSecurity()
{
	int i;
	//更新系统可利用资源量
	for (i = 0; i < resourseType; i++)
	{
		work[i] = available[i];
	}

	int allFinish = 0;
	//把未完成进程置为0
	for (i = 0; i < customerNumber; i++)
	{
		//判断当前进程是否已经完成并且可以回收资源

		//如果已经全部完成
		if (isFinish(i))
		{
			Finish[i] = 1;
			allFinish++;
		}
		else
		{
			Finish[i] = 0;
		}
	}

	int r = 0;//表示当前要判断是否要进行预分配的进程的下标
	int safeIndex = 0;//安全序列的下标
	int temp = 0;//临时变量
	int pNum = 0;//保存临时变量的个数
	//预分配开始,当进程没有全部完成时,一直执行循环
	while (allFinish != customerNumber)
	{
		num = 0;
		//判断是否可以预分配
		for (i = 0; i < resourseType; i++)
		{
			if (need[r][i] <= work[i] && Finish[r] == 0)//判断是否可以预分配
			{
				num++;
			}
		}

		//可以预分配
		if (num == resourseType)
		{
			//输出进程Pr的各项信息
			SafeInfo(work, r);
			//回收资源
			for (i = 0; i < resourseType; i++)
			{
				work[i] = work[i] + allocation[r][i];
			}
			//完成的进程数增加
			allFinish++;
			//保存安全序列
			safeSeries[safeIndex] = r;
			safeIndex++;
			//当前进程安全
			Finish[r] = 1;
		}


		r++;//该式必须在此处	
		if (r >= customerNumber)
		{
			r = r % customerNumber;
			if (temp == allFinish)//temp记录的是上一次循环分配后所有的进程完成数,将上一次进程数跟这次预分配后的进程数
			{					  //进行对比,如果相等,则是不安全的情况,直接break;否则是安全的情况,继续执行
				break;
			}
			temp = allFinish;//更新完成的进程数
		}
		pNum = allFinish;//保存安全序列的个数
	}

	//判断系统是否安全
	for (i = 0; i < customerNumber; i++)
	{
		if (Finish[i] == 0)
		{
			return 0;
		}
	}

	//打印安全序列
	printf("\n安全序列为:");
	for (i = 0; i < customerNumber; i++)
	{
		if (isFinish(i))
		{
			pNum--;
		}
	}
	for (i = 0; i < pNum; i++)
	{
		printf("%d ", safeSeries[i]);
	}
	return 1;
}

//判断进程资源请求的安全性
void judRequestSecurity()
{
	//输入预分配的资源编号和各类资源量
	int curProcess;
	printf("请输入预分配资源的进程的编号:");
	scanf("%d", &curProcess);
	getchar();

	int i;
	for (i = 0; i < resourseType; i++)
	{
		printf("请输入给 P%d 预分配的第 %d 类资源量:", curProcess, i + 1);
		scanf("%d", &request[i]);
		getchar();
	}

	//作为安全性的判断变量
	num = 0;
	//进行判断预分配是否合理
	for (i = 0; i < resourseType; i++)
	{
		if (request[i] > need[curProcess][i])
		{
			printf("\n分配错误!请求分配资源量大于所需要的资源量!\n");
			printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
			return;
		}
		else if (request[i] > available[i])
		{
			printf("\n分配错误!请求分配资源量大于可利用资源量!\n");
			printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
			return;
		}
		else
		{
			num++;
		}
	}

	//分配合理,则试探性地分配
	if (num == resourseType)
	{
		num = 0;
		for (i = 0; i < resourseType; i++)
		{
			available[i] -= request[i];
			allocation[curProcess][i] += request[i];
			need[curProcess][i] -= request[i];
			if (need[curProcess][i] == 0)
			{
				num++;
			}
		}
		//分配合理并且此次分配后该进程执行结束,回收资源
		if (num == resourseType)
		{
			for (i = 0; i < resourseType; i++)
			{
				available[i] += allocation[curProcess][i];
			}
			printf("\n进程 P%d 执行完毕,所占用资源全部释放!\n", curProcess);
		}
		else
		{
			printf("\n进程 P%d 未执行完毕,等待\n", curProcess);
		}
	}

	//检查分配后系统是否安全,如果不安全,则收回分配的资源
	printf("\n------------------------------------------------------------------------------------\n");
	printf("当前系统各类资源剩余量:");
	for (int i = 0; i < resourseType; i++)
	{
		printf("%d ", available[i]);
	}

	printf("\n\n当前系统进程状况:\n");
	printf(" Name\t Work\t Need\tAllocation\tWork+Allocation\t Finish\n");
	if (!judSystemSecurity_1())
	{
		for (i = 0; i < resourseType; i++)
		{
			available[i] += request[i];
			allocation[curProcess][i] -= request[i];
			need[curProcess][i] += request[i];
		}
		printf("\n\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT  OBTAIN RESOURCES IMMEDIATELY", curProcess);
	}
	else
	{
		printf("\n\nRESOURCE SECURITY!!!\n\nCUSTOMER P%d CAN OBTAIN RESOURCES IMMEDIATELY", curProcess);
	}
	printf("\n------------------------------------------------------------------------------------\n");
	return;
}

//菜单
void showMenu()
{
	printf("  ====================菜单栏=====================\n");
	printf("\n\t       0、input datas\n");
	printf("\n\t       1、judge the system security\n");
	printf("\n\t       2、judge the request security\n");
	printf("\n\t       3、quit\n");
	printf("\n  ===============================================\n");
	return;
}

//检测用户按键输入
void keyDown()
{
NEXT:
	;
	int hit;
	printf("请输入你的选择:");
	scanf("%d", &hit);
	switch (hit)
	{
	case 0:
	NEXT_1:
		flag = 1;
		InitStastic();
		break;
	case 1://判断系统安全性
		if (flag)
		{
			printf("\n------------------------------------------------------------------------------------\n");
			printf("当前系统各类资源剩余量:");
			for (int i = 0; i < resourseType; i++)
			{
				printf("%d ", available[i]);
			}

			printf("\n\n当前系统进程状况:\n");
			printf(" Name\t Work\t Need\tAllocation\tWork+Allocation\t Finish\n");
			if (judSystemSecurity_1())
			{
				printf("\n\nSYSTEM SECURITY!!!");
			}
			else
			{
				printf("\n\nSYSTEM  INSUFFICIENT!!!");
			}
			printf("\n------------------------------------------------------------------------------------\n");
		}
		else
		{
			printf("还未输入数据!请先输入相关数据\n");
			goto NEXT_1;
		}

		break;
	case 2://判断进程请求的安全性
		if (flag)
		{
			judRequestSecurity();
		}
		else
		{
			printf("还未输入数据!请先输入相关数据\n");
			goto NEXT_1;
		}
		break;
	case 3://退出
		printf("\n正常退出!\n");
		exit(-1);
	default:
		printf("\n输入错误,请重新输入指令!\n");
		system("pause");
		system("cls");
		showMenu();
		goto NEXT;
		break;
	}
}

void InitStastic()
{
	printf("Input the type of resource and number of customer:\n");
	scanf("%d%d", &resourseType, &customerNumber);
	getchar();

	printf("\nInput the amount of resource (maximum , allocated) of each customer:\n");
	int i, j;
	for (i = 0; i < customerNumber; i++)
	{
		for (j = 0; j < resourseType; j++)
		{
			printf("请输入进程 P%d 的第 %d 类资源的最大需求量:", i, j + 1);
			scanf("%d", &max[i][j]);
			getchar();
		}
		printf("\n\n");
		for (j = 0; j < resourseType; j++)
		{
			printf("请输入进程 P%d 的第 %d 类资源的已占用资源量:", i, j + 1);
			scanf("%d", &allocation[i][j]);
			getchar();
		}
		printf("\n\n");
		for (j = 0; j < resourseType; j++)
		{
			need[i][j] = max[i][j] - allocation[i][j];
		}
	}

	printf("\nInput  the amout of  resources(available):\n");
	for (i = 0; i < resourseType; i++)
	{
		printf("请输入第%d类资源的可利用量:", i + 1);
		scanf("%d", &available[i]);
		getchar();
	}

	printf("\n数据录入成功!\n");
	return;
}

int main(int argc, char* argv[])
{

	while (1)
	{
		showMenu();
		keyDown();
		system("pause");
		system("cls");
	}

	return 0;
}

菜单栏:

操作系统-资源分配银行家算法_第1张图片

输入示例:

操作系统-资源分配银行家算法_第2张图片
操作系统-资源分配银行家算法_第3张图片
操作系统-资源分配银行家算法_第4张图片

输出示例:

操作系统-资源分配银行家算法_第5张图片
操作系统-资源分配银行家算法_第6张图片
操作系统-资源分配银行家算法_第7张图片

有任何问题可以留言交流,我一定及时回复

你可能感兴趣的:(操作系统,操作系统,银行家算法)