操作系统 | 实验三 进程死锁

一、实验目的

  1. 理解银行家算法。
  2. 掌握进程安全性检查的方法及资源分配的方法。

二、实验内容

编制模拟银行家算法的程序,并以下面给出的例子验证所编写的程序的正确性。
某系统有A、B、C、D4类资源共5个进程(PO、P1、P2、P3、P4)共享,各进程对资源的需求和分配情况如下表所示。各进程对资源的需求和分配情况表:
在这里插入图片描述
现在系统中A、B、C、D4类资源分别还剩1、5、2、0个,请按银行家算法回答下列问题:

  • 在系统是否处于安全状态?
  • 如果现在进程Pl提出需要(0、4、2、0)个资源的请求,系统能否满足它的请求?

三、实验步骤

3.1 变量以及描述

变量 描述
int available[100]; 可利用资源数组
int max[50][100]; 最大需求矩阵
int allocation[50][100]; 分配矩阵
int need[50][100]; 还需资源矩阵
int request[50][100]; 申请资源数量
int finish[50]; 完成
int p[50]; 进程
int m = 0; m个进程
int n = 0; n个资源

3.2 函数以及功能

函数名称 功能描述
int IsSafe() 判断是否是安全状态
int main() Main函数
Void DisplayInfo() 展示信息

四、实验代码

#include<stdio.h>

#define SYSINFO "银行家算法演示系统" // 系统信息 
#define AUTHOR "Yrani - 依然" //作者 

int available[100];//可利用资源数组
int max[50][100];//最大需求矩阵
int allocation[50][100];//分配矩阵
int need[50][100];//需求矩阵
int request[50][100]; //请求矩阵
int finish[50]; //完成
int p[50];//进程
int m = 0;//m个进程
int n = 0;//n个资源

/**
* 	@Author: Yrani - 依然
* 	@Date: 2022-04-18 20:00:17
* 	@LastEditTime: 2022-04-20 20:55:00
* 	@keywords: 银行家算法、安全态
**/

//判断是否是安全状态
int IsSafe()
{
	int i = 0, j = 0, l = 0;
	int Work[100];//可利用资源数组
	for(i = 0; i < n; i++)
	{
		Work[i] = available[i];
	}

	for(i = 0; i < m; i++)
	{
		finish[i] = 0;
	}

	for(i =0; i < m; i++)
	{
		if(finish[i] == 1)
		{
			continue;
		}
		else
		{
			for(j = 0; j < n; j++)
			{
				if(need[i][j] > Work[j])
				{
					break;
				}
			}
			if(j == n)
			{
				finish[i] = 1;
				for(int k = 0; k < n; k++)
					Work[k] += allocation[i][k];
				p[l++] = i;
				i = -1;
			}
			else
			{
				continue;
			}
		}
		if(l == m)
		{
			printf("系统是安全的\n");
			printf("安全序列是:\n");
			for(i = 0; i < l; i++)
			{
				printf("%d",p[i]);
				if(i != l-1)
					printf("-->");
			}
			printf("\n");
			return 1;
		}
	}
}


//展示信息
void DisplayInfo()
{
	//显示调度算法菜单,可供用户选择优先权调度算法和时间片轮转调度算法
	printf("★★★★★★★★★★★★★★★★★\n");
	printf("★☆☆☆%s☆☆☆★\n",SYSINFO);
	printf("☆☆☆☆ @Author:%s ☆☆☆☆★\n",AUTHOR);
	printf("★★★★★★★★★★★★★★★★★\n");
}

//main函数、银行家算法
int main()
{
	DisplayInfo();
	 
	int i = 0, j = 0, mi = 0;
	printf("输入进程的数目:\n");
	scanf("%d", &m);
	printf("输入资源的种类:\n");
	scanf("%d", &n);
	printf("输入每个进程最多所需的各资源数,按照%dx%d矩阵输入\n",m,n);

	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n; j++)
		{
			scanf("%d", &max[i][j]);
		}
	}

	printf("您输入的每个进程最多所需的各资源数如下:\n") ;
	for (int i = 0; i < m; i ++ )
	{
		for(j = 0; j < n; j++)
		{
			printf("%d ", max[i][j]);
		}
		puts("");
	}

	printf("输入每个进程已分配的各资源数,也按照%dx%d矩阵输入\n",m ,n);

	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n; j++)
		{
			scanf("%d", &allocation[i][j]);
			need[i][j] = max[i][j] - allocation[i][j];
			if(need[i][j] < 0)
			{
				printf("你输入的第%d个进程所拥有的第%d个资源数错误,请重新输入:\n", i + 1, j + 1);
				j--;
				continue;
			}
		}
	}

	printf("您输入的每个进程已分配的各资源如下:\n") ;
	for (int i = 0; i < m; i ++ )
	{
		for(j = 0; j < n; j++)
		{
			printf("%d ", allocation[i][j]);
		}
		puts("");
	}

	printf("根据计算need矩阵如下:\n") ;
	for (int i = 0; i < m; i ++ )
	{
		for(j = 0; j < n; j++)
		{
			printf("%d ", need[i][j]);
		}
		puts("");
	}

	printf("请输入各个资源现有的数目:\n");
	for(i = 0; i < n; i++)
	{
		scanf("\n%d", &available[i]);
	}

	IsSafe();
	while(1)
	{

		printf("输入要申请资源的进程号(注:第1个进程号为0,以此类推)\n");
		scanf("\n%d", &mi);
		printf("输入进程所请求的各资源的数量\n");
		for(i = 0; i < n; i++)
		{
			scanf("\n%d", &request[mi][i]);
		}

		for(i = 0; i < n; i++)
		{
			if(request[mi][i] > need[mi][i])
			{
				printf("你输入的请求数超过进程的需求量!\n");
				return 0;
			}
			if(request[mi][i] > available[i])
			{
				printf("你输入的请求数超过系统有的资源数!\n");
				return 0;
			}
		}

		for(i = 0; i < n; i++)
		{
			available[i] -= request[mi][i];
			allocation[mi][i] += request[mi][i];
			need[mi][i] -= request[mi][i];
		}

		if(IsSafe()==1)
		{
			printf("同意分配请求!\n");
			return 0;
		}
		else
		{
			printf("你的请求被拒绝\n");
			for(i = 0; i < n; i++)
			{
				available[i] += request[mi][i];
				allocation[mi][i] -= request[mi][i];
				need[mi][i] += request[mi][i];
			}

			for(i = 0; i < m; i++)
			{
				finish[i] = 0;
			}

			char YesOrNo;
			printf("你还想再次请求分配吗?是请按y/Y,否按n/N,再确定 \n");
			while(1)
			{
				scanf("\n%c", &YesOrNo);
				if(YesOrNo == 'y' || YesOrNo == 'Y' || YesOrNo == 'n' || YesOrNo == 'N') //输入 
				{
					break;
				}
				else
				{
					printf("请按要求输入!\n");
					continue;
				}
			}

			if(YesOrNo == 'y'|| YesOrNo == 'Y')
			{
				continue;
			}
			else break;
		}
	}

	return 0;
}

五、实验结果

算法演示在这里插入图片描述
输入进程数5,资源种类4以及最大需求矩阵
在这里插入图片描述

输入已分配矩阵
在这里插入图片描述

再输入各个资源现有的数目并计算出安全序列

在这里插入图片描述

输入请求资源的进程号
在这里插入图片描述

输入请求的资源在这里插入图片描述

输入错误的单词
在这里插入图片描述

输入y然后输入申请的进程和资源数
在这里插入图片描述

六、实验体会总结

体会:

  • 此次实验是银行家算法的代码实现,使用的是c语言去实现该算法,模拟银行家算法的流程。
  • 相较于前两次实验,此次实验代码较短较为简单,调试修改起来很快,但是调试的过程中也遇到了不少的坑点,需要自己仔细推敲,才能理解其中的原理与逻辑。
  • 该实验中没有用到结构体也没有用到指针,数组用的是最多的,可以看出数组的作用非常之大,需要巧妙利用。

总结:

  • 银行家算法是一个避免死锁的著名算法,简单来解释银行家算法就是当一个进程申请使用资源的时候,银行家算法通过先试探分配给该进程资源,然后通过安全性算法判断分配后的系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待。
  • 对于知识的学习,知道自己还有很多的不足,所以需要多加努力,多多反省,多多总结。
  • 4
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值