操作系统死锁避免——银行家算法

银行家算法主要分为两个部分,第一部分是银行家进行资源分配可行性检查;第二部分是安全性算法对模拟分配后是否有一个不会产生进程死锁的安全序列进行检查。

银行家算法的主要数据结构如下:

#include <iostream>
using namespace std;

const int  max_resource = 10; //最大的资源种类
const int  max_progress = 5;  //最大的进程数量
const int  m = 3;             //系统可分配资源种类
//typedef struct banker *bankerptr;

//银行家数据结构
typedef struct banker {
	int available[max_resource];               //可利用资源矢量
	int max[max_progress][max_resource];       //最大需求矩阵
	int need[max_progress][max_resource];      //每个进程的还需要的资源矩阵
	int allocation[max_progress][max_resource];//已分配资源矩阵
}*bankerptr;
//初始化银行家
void Init_banker(bankerptr Banker,int a,int b,int c) {
	Banker->available[0] = a;
	Banker->available[1] = b;
	Banker->available[2] = c;
		for (int i = 0; i < max_progress; i++) {
			for (int j = 0; j < max_resource; j++) {
				Banker->max[i][j] = 0;
				Banker->need[i][j] = 0;
				Banker->allocation[i][j] = 0;
			}
		}
}

void print(bankerptr Banker) {
	//打印界面
	//system("cls");
	cout << "*****************************" << endl;
	cout << "系统的可利用资源表(availble):" << endl;
	cout << "资源类型:A\tB\tC" << endl;
	cout << "          " << Banker->available[0] << "\t" << Banker->available[1] << "\t" << Banker->available[2] << endl;
	cout << "各进程尚需的资源表(need):" << endl;
	cout << "资源类型:A\tB\tC" << endl;
	for (int i = 0; i < max_progress; i++) {
		cout << i + 1 << " 号进程:" << Banker->need[i][0] << "\t" << Banker->need[i][1] << "\t" << Banker->need[i][2] << endl;
	}
	cout << "系统已分配资源表(allocation):" << endl;
	cout << "资源类型:A\tB\tC" << endl;
	for (int i = 0; i < max_progress; i++) {

		cout << i + 1 << " 号进程:" << Banker->allocation[i][0] << "\t" << Banker->allocation[i][1] << "\t" << Banker->allocation[i][2] << endl;
	}
	cout << "进程最大需求资源表(max):" << endl;
	cout << "资源类型:A\tB\tC" << endl;
	for (int i = 0; i < max_progress; i++) {

		cout << i + 1 << " 号进程:" << Banker->max[i][0] << "\t" << Banker->max[i][1] << "\t" << Banker->max[i][2] << endl;
	}
	cout << "*****************************" << endl;
}

int n = 0;
int number = 0;

class Progress {
	int need[3];   //需求矩阵
	int num;       //进程的编号
	int Security(bankerptr p);
public:
	Progress(int a, int b, int c,bankerptr Banker):num(number) {
		need[0] = a;
		need[1] = b;
		need[2] = c;
		Banker->need[num][0] = a;
		Banker->need[num][1] = b;
		Banker->need[num][2] = c;
		Banker->max[num][0] = a; 
		Banker->max[num][1] = b;
		Banker->max[num][2] = c;
		n++;
		number++;
	}
	~Progress() {}
	void Request(bankerptr Banker,int a,int b,int c);//每个进程只需要调用这个借口就可以了
};
//安全性算法
int Progress::Security(bankerptr p) {
	//如果存在安全序列就返回1,否则返回0
	int progress[max_progress];
	banker Banker = *p;//这里如果用指针的话会改变p的内容
	int count = 0;
	int count1 = 0;
	int sign = 1; //用于判断该进程是否可以加入安全队列
	int Link[max_progress] = {0};//用于存放安全序列
	for (int k = 0; k < max_progress; k++) {
		//初始化进程数组,如果是没有分配资源的进程行就为2,否则为0
		if (Banker.allocation[k][0] == 0 && Banker.allocation[k][1] == 0 && Banker.allocation[k][2] == 0)
			progress[k] = 2;
		else {
			progress[k] = 0;
			count1++;//表示需要加入到安全队列的进程数
		}
	}
	int h = count1;
	while (h) {
		//while要求循环最大进程数的次数,因为有可能每次循环只会添加一个进程进入安全队列
		h--;
		for (int i = 0; i < max_progress; i++) {
			if (progress[i] == 2) {
				//表示没有为该进程分配资源
				continue;
			}
			for (int j = 0; j < 3; j++) {
				if (Banker.allocation[i][j] > Banker.available[j]) {
					sign = 0;
					break;
				}
			}
			if (sign != 0) {
				//该进程可以加入安全队列
				progress[i] = 1;//表示该进程加入了安全队列
				Link[count++] = i+1;
				if (count == count1) {
					//表示安全序列已满
					cout << "安全序列为:";
					for (int i = 0; i<count-1; i++) {
						cout << "P" << Link[i] << "->";
					}
					cout << "P" << Link[i] << endl;
					return 1;
				}
				for (int j = 0; j < 3; j++) {
					Banker.available[j] += Banker.allocation[i][j];//将分配的资源回收
				}
			}
			else {
				//该进程不能加入安全队列,继续判断其他进程
				sign = 1;
				continue;
			}
		}
	}
	return 0;
}
//进程申请资源
void Progress::Request(bankerptr Banker,int a,int b, int c) {
	//先检查申请的资源数量是否小于需求数量
	cout << num + 1 << "号进程申请资源(A,B,C):" << "(" << a << "," << b << "," << c << ")" <<endl;
	int request[3];
	request[0] = a;
	request[1] = b;
	request[2] = c;
	if (a > Banker->need[this->num][0] || b > Banker->need[this->num][1] || c > Banker->need[this->num][2]) {
		cout << num+1 << "号进程申请的资源超过其需求资源,申请资源不成功..." << endl;
		return;
	}
	//如果申请的资源数量小于需求数量,检查其是否小于可分配资源的数量
	else {
		if (a > Banker->available[0] || b > Banker->available[1] || c > Banker->available[2]) {
			cout << num+1  << "号进程申请的资源超过系统能分配的资源,申请资源不成功..." << endl;
			return;
		}
		//如果资源数量足够就先模拟分配资源然后执行安全算法
		else {
			bankerptr p = Banker;
			for (int i = 0; i < 3; i++) {
				p->available[i] -= request[i];
				p->allocation[this->num][i] += request[i];
				p->need[this->num][i] -= request[i];
				
			}
			//接下来执行安全算法
			int h = Security(p);
			if (h == 1) {
				cout <<num+1<< "号进程申请资源成功..." << endl;
				//真的将资源分配给该进程
				Banker = p;
				return;
			}
			else {
				cout <<num+1<< "号进程申请资源失败..." << endl;
				return;
			}
		}
	}
}

int main()
{
	bankerptr Banker = (bankerptr)malloc(sizeof(banker));
	Init_banker(Banker,5,4,8);
	print(Banker);
	Progress P1(4, 5, 6, Banker);
	Progress P2(1, 2, 1, Banker);
	Progress P3(2, 1, 2, Banker);
	Progress P4(1, 3, 2, Banker);
	Progress P5(4, 1, 1, Banker);
	P1.Request(Banker, 1, 1, 2);
	//print(Banker);
	//system("pause");
	P2.Request(Banker, 1, 2, 1);
	//print(Banker);
	//system("pause");
	P3.Request(Banker, 2, 1, 2);
	//print(Banker);
	//system("pause");
	P4.Request(Banker, 1, 3, 2);
	//print(Banker);
	//system("pause");
	P5.Request(Banker, 4, 1, 1);
	//print(Banker);
	//system("pause");
	P1.Request(Banker, 1, 3, 1);
	print(Banker);
    return 0;
}

运行结果如下:


PS:我在写安全性算法的时候一直没有很明确的思路,因为我一直无法把所有可能的结果都找出来(作为一个菜鸟我表示很无奈),后来我借鉴了 https://blog.csdn.net/csd1993/article/details/41945021 这篇文章的安全性算法,但是还是觉得无法把所有可能的情况都找出来(不知道是不是我的理解不够到位)。综上所述,上面这段代码还是有待改进的。

参考文章:https://blog.csdn.net/csd1993/article/details/41945021

参考书籍: 王道 《2018年操作系统考研复习指导》

猜你喜欢

转载自blog.csdn.net/haohulala/article/details/80691300