计算机操作系统:死锁的避免

目录

1 实验名称

2 实验目的

3 实验内容

4 实验原理及流程图

5 实验源代码

6 实验结果

7 实验总结


1 实验名称

       死锁的避免

2 实验目的

       通过使用银行家算法实现系统资源的分配和安全性检查模拟,深刻理解操作系统的死锁避免算法。

3 实验内容

       C语言完成“银行家算法”,记录程序运行结果,完成实验报告。要求:

       1)设计五个进程{P0,P1,P2,P3,P4}共享三类资源{A,B,C}的系统,{A,B,C}的资源总数量分别为10,5,7。

       2)并发进程可动态地申请资源和释放资源(程序交互输入申请或释放资源数量),系统按各进程的申请动态地分配资源。

       3)每当进程动态申请资源或释放资源时,模拟程序应能及时输出各个进程在此时刻的资源分配表、系统可用资源量和安全序列等资源分配信息和安全检查信息。

4 实验原理及流程图

       银行家算法:进程可动态的申请和释放资源,系统按照各进程的申请动态地分配资源,在T0时刻的资源分配情况如下表:

1

Name

Max

Allocation

Need

Available

2

P0

7,5,3

0,1,0

7,4,3

3,3,2

3

P1

3,2,2

2,0,0

1,2,2

4

P2

9,0,2

3,0,2

6,0,0

5

P3

2,2,2

2,1,1

0,1,1

6

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 则表示系统安全,否则为不安全。

流程图:

5 实验源代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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){
			SafeInfo(work, r);//输出进程Pr的各项信息
			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\n
CUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
			return;
		}
		else if (request[i] > available[i]){
			printf("\n分配错误!请求分配资源量大于可利用资源量!\n");
			printf("\nRESOURCE INSECURITY!!!\n\n
CUSTOMER 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\n
CUSTOMER P%d CAN NOT  OBTAIN RESOURCES IMMEDIATELY", curProcess);
	}
	else{
		printf("\n\nRESOURCE SECURITY!!!\n\n
CUSTOMER P%d CAN OBTAIN RESOURCES IMMEDIATELY", curProcess);
	}
	printf("\n----------------------------------------------
--------------------------------------\n");
	return;
}

6 实验结果

7 实验总结

       为实现银行家算法,每个新进程在进入系统时它必须申明在运行过程中,可能需要的每种资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量。当某一进程请求时,系统会自动判断请求量是否小于进程最大所需,同时判断请求量是否小于当前系统资源剩余量。若两项均满足,则系统试分配资源并执行安全性检查算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

茜茜西西CeCe

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

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

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

打赏作者

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

抵扣说明:

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

余额充值