银行家算法的模拟与实现

银行家算法的模拟与实现

一、实验目的

(1) 进一步了解进程的并发执行。
(2) 加强对进程死锁的理解,理解安全状态与不安全状态的概念。
(3) 掌握使用银行家算法避免死锁问题。

二、总体设计

2.1实验基本知识及原理

(1)基本概念

死锁:多个进程在执行过程中,因为竞争资源会造成相互等待的局面。如果没有外力作用,这些进程将永远无法向前推进。此时称系统处于死锁状态或者系统产生了死锁。
安全序列:系统按某种顺序并发进程,并使它们都能达到获得最大资源而顺序完成的序列为安全序列。
安全状态:能找到安全序列的状态称为安全状态,安全状态不会导致死锁。
不安全状态:在当前状态下不存在安全序列,则系统处于不安全状态。

(2)银行家算法

银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要满足多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。

在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其它进程使用资源。如果资源分配不当,就会发生进程循环等待资源,则进程都无法继续执行下去的死锁现象。

当一进程提出资源申请时,银行家算法执行下列步骤以决定是否向其分配资源:
1)检查该进程所需要的资源是否已超过它所宣布的最大值。
2)检查系统当前是否有足够资源满足该进程的请求。
3)系统试探着将资源分配给该进程,得到一个新状态。
4)执行安全性算法,若该新状态是安全的,则分配完成;若新状态是不安全的,则恢复原状态,阻塞该进程。

2.2 实验内容

本实验的内容是要通过编写和调试一个模拟系统动态分配资源的银行家算法程序,有效地避免死锁发生。具体要求如下:
(1) 初始化时让系统拥有一定的资源;
(2) 用键盘输入的方式允许进程动态申请资源;
(3) 如果试探分配后系统处于安全状态,则修改系统的资源分配情况,正式分配资源;
(4) 如果试探分配后系统处于不安全状态,则提示不能满足请求,恢复原状态并阻塞该进程。

三、详细设计
3.1 银行家算法中的数据结构与流程图

(1)数据结构:
资源总量向量 Resource, m 维,表示 m 种资源的总量。
可用资源向量 Available, m 维,表示未分配的各种可用资源数量。
需求矩阵Need, nm 矩阵,表示 n 个进程对 m 类资源的最大需求。
分配矩阵 Allocation , n
m 矩阵,表示 n 个进程已分配的各种资源数。

代码实现
#define _CRT_SECURE_NO_WARNINGS // VS用scanf()函数才需要的定义

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

#define  M  4 //总进程数
#define  N  3 //资源种类
int ALL_RESOURCE[3] = { 9, 3, 6 };//各种资源的数目总和
int MAX[M][N] = { { 3, 1, 2 }, { 6, 1, 3 }, { 3, 1, 4 }, { 4, 2, 2 } }; //M个进程对N类资源最大资源需求量
int AVAILABLE[N]; //系统可用资源数
int ALLOCATION[4][3] = { { 1, 0, 0 }, { 6, 1, 2 }, { 2, 1, 1 }, { 0, 0, 2 } }; //M个进程已经得到N类资源的资源量
int NEED[M][N]; //M个进程还需要N类资源的资源量
int Request[N]; //请求资源个数

void showdata() //函数showdata,输出资源分配情况
{
	int i, j;
	printf("各种资源的总数量(all):[");
	for (j = 0; j < N; j++){
		printf(" %d", ALL_RESOURCE[j]);
	}
	printf(" ]\n\n");
	
	printf("系统目前各种资源可用的数为(available):[");
	
	for (j = 0; j < N; j++){
		printf(" %d", AVAILABLE[j]);
	}
	printf(" ]\n\n");

	printf(" 各进程已经得到的资源量(allocation): \n\n");
	printf("       资源0     资源1     资源2\n");
	for (i = 0; i<M; i++)
	{
		printf("进程p%d:    ", i);
		for (j = 0; j < N; j++){
			printf("%d       ", ALLOCATION[i][j]);
		}
		printf("\n");
	}
	printf("\n");
	printf(" 各进程还需要的资源量(need):\n\n");
	printf("       资源0     资源1    资源2\n");
	for (i = 0; i < M; i++){
		for (i = 0; i<M; i++)
		{
			printf("进程p%d:   ", i );
			for (j = 0; j < N; j++){
				printf("%d        ", NEED[i][j]);
			}
			printf("\n");
		}
	}
	
	printf("\n");
}

void changdata(int k) //分配资源
{
	int j;
	for (j = 0; j<N; j++)
	{
		AVAILABLE[j] = AVAILABLE[j] - Request[j];
		ALLOCATION[k][j] = ALLOCATION[k][j] + Request[j];
		NEED[k][j] = NEED[k][j] - Request[j];
	}
}

void rstordata(int k) //恢复现场
{
	int j;
	for (j = 0; j < N; j++)
	{
		AVAILABLE[j] = AVAILABLE[j] + Request[j];
		ALLOCATION[k][j] = ALLOCATION[k][j] - Request[j];
		NEED[k][j] = NEED[k][j] + Request[j];
	}
}


int chkerr(int s) //函数chkerr,检查是否安全
{
	int i = s;
	int flag = 0;
	int *FINISH = (int *)malloc(sizeof(int) * M);
	int *WORK = (int *)malloc(sizeof(int)* N);
	int *array = (int *)malloc(sizeof(int)* M);
	int cnt = 0;
	int j;

	memset(FINISH, 0, sizeof(FINISH));
	memset(WORK, 0, sizeof(WORK));
	printf("系统当前可用资源:");
	for (j = 0; j < N; j++)
	{
		WORK[j] = AVAILABLE[j]; // 各分配的资源回收
		printf("%d ", WORK[j]);
	}
	printf("\n");
	{
		int j;
		for (j = 0; j < N; j++){ // 资源检查
			if (NEED[i][j] > AVAILABLE[j]){ // 进程i所需要的资源j能否被满足
				flag = 1; // 有不满足的,就退出
				break;
			}
		}
	}
	
	if (flag == 0){
		int j;
		FINISH[i] = 1; //i号进程,可以执行
		printf("进程p%d执行\n", i);
		printf("系统当前可用资源:");
		for (j = 0; j < N; j++)
		{
			WORK[j] += ALLOCATION[i][j]; // 各分配的资源回收
			printf("%d ", WORK[j]);
		}
		printf("\n");
		array[cnt++] = i;
	}

	while (1){
		int i;
		int flag1 = 0;
		
		for (i = 0; i < M; ){
			int sum = 0;
			int k;
			for (k = 0; k < M; k++){
				sum += FINISH[k];
			}
			if (sum == M){
				int ij;
				printf("存在安全序列:");
				for (ij = 0; ij < M; ij++){
					printf("p%d ", array[ij]);
				}
				printf("\n");
				printf("【经安全性检查,系统安全,本次分配成功。】\n");
				printf("\n");
				return 1;
			}
	
			if (FINISH[i] != 1){
				flag1 = 0;
				for (int j = 0; j < N; j++){ // 资源检查
					if (NEED[i][j] > WORK[j]){ // 进程i所需要的资源j能否被满足
						flag1 = 1; // 有不满足的,就退出
						break;
					}
				}
			}

			if (flag1 == 0 && FINISH[i] != 1 ){ // 表示i进程没执行,且可以执行
				int j;
				FINISH[i] = 1; //i号进程,可以执行
				printf("进程p%d执行\n", i);
				printf("系统当前可用资源:");
				for (j = 0; j < N; j++)
				{
					WORK[j] +=  ALLOCATION[i][j]; // 各分配的资源回收
					printf("%d ", WORK[j]);
				}
				printf("\n");
				array[cnt++] = i;
				i = 0;
			}
			else{ // 不能执行判断下一个进程
				i++;
			}
		}
		printf("\n");
		printf("【系统不安全!!! 本次资源申请不成功!!!】\n");
		printf("\n");
		return 0;

	}
}

void bank()   //银行家算法主体
{
	int i = 0, j = 0;
	char flag = 'Y';

	while (flag == 'Y' || flag == 'y')
	{
		i = -1;
		while (i < 0 || i >= M)
		{
			printf(" 请输入需申请资源的进程号(从P0到P%d,否则重输入!):", M - 1);
			printf("P");
			scanf("%d", &i);
			while(i < 0 || i >= M){
				printf(" 输入的进程号不存在,重新输入!\n");
				printf(" 请输入需申请资源的进程号(从P0到P%d,否则重输入!):", M - 1);
				printf("P");
				scanf("%d", &i);
			}
			printf(" 请输入进程P%d申请的资源数:\n", i);
			for (j = 0; j<N; j++)
			{
				printf(" 资源%d:", j);
				scanf("%d", &Request[j]);
				if (Request[j]>NEED[i][j]) //若请求的资源数大于进程还需要i类资源的资源量j
				{
					printf(" 进程P%d申请的资源数大于进程P%d还需要%d类资源的资源量!", i, i, j);
					printf("申请不合理,出错!请重新选择!\n\n");
					flag = 'N';
					break;
				}
				else
				{
					if (Request[j] > AVAILABLE[j]) //若请求的资源数大于可用资源数
					{
						printf(" 进程P%d申请的资源数大于系统可用%d类资源的资源量!", i, j);
						printf("申请不合理,出错!请重新选择!\n\n");
						flag = 'N';
						break;
					}
				}
			}
			if (flag == 'Y' || flag == 'y')
			{
				changdata(i); //调用changdata(i)函数,改变资源数
				if (chkerr(i)) //若系统安全
				{
					
					printf("\n");
					printf(" 是否继续银行家算法演示,按'Y'或'y'键继续,按'N'或'n'键退出演示: ");
					scanf("%*c%c", &flag);
					rstordata(i); //调用rstordata(i)函数,恢复资源数
					showdata();   //输出资源分配情况
				}
				else {      //若系统不安全
					
					printf("\n");
					printf(" 是否继续银行家算法演示,按'Y'或'y'键继续,按'N'或'n'键退出演示: ");

					scanf("%*c%c", &flag);
					showdata(); //输出资源分配情况
				}
			}
			else      //若flag=N||flag=n
			{
				printf("\n");
				printf(" 是否继续银行家算法演示,按'Y'或'y'键继续,按'N'或'n'键退出演示: ");

				scanf("%*c%c", &flag);
				showdata();
			}
			
		}
	}
}

//主函数
int main()
{
	int i = 0, j = 0, p;
	//初始化资源数量
	for (j = 0; j<N; j++)
	{
		p = ALL_RESOURCE[j];
		for (i = 0; i<M; i++)
		{
			p = p - ALLOCATION[i][j];//减去已经被占据的资源
			AVAILABLE[j] = p;
			if (AVAILABLE[j]<0)
				AVAILABLE[j] = 0;
		}
	}
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < N; j++){
			NEED[i][j] = MAX[i][j] - ALLOCATION[i][j];
		}	
	}
	
	showdata();
	bank();

	return 0;
}

运行结果

在这里插入图片描述

在这里插入图片描述

  • 30
    点赞
  • 149
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_Hello Spring

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

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

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

打赏作者

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

抵扣说明:

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

余额充值