操作系统之银行家算法的代码实现

银行家算法

疫情 期间,上操作系统原理课,因为在家,所以上的浑浑噩噩,上周老师让提交银行家算法实验报告,自己看书弄了挺长时间的基本实现课本(汤小丹老师)上的案例,为了锻炼自己使用Markdown的能力,写下这篇文章。

1、银行家算法的详解

      这方面我就不多介绍(因为时间问题,来不及作图),在csdn上看到几篇博客,写的很详细。

银行家算法详解(过程比较详细)
银行家算法流程图

2、银行家算法的代码实现

   按照课本上算法的描述实现算法的时候,自己起初出了一些问题。我们知道,银行家算法的核心
是安全性检查算法:当我们申请调用资源给某个进程 i 的时候,系统会先试探性地将资源分配给进程 i,
然后调用安全性检查算法,查询是此时是否存在安全序列,如果存在的话,那么表示这次资源的分配是没
有问题的,如果不存在安全序列,则表示此次资源的申请是危险的,回收已分配的资源,并让进程 i等待
1、改进
   首次实现算法的时候,在安全性算法那里与大多数人的想法一样,套用两次循环来寻找满足
条件(Finish[i]=0&&Work[i]<=Need[i][j])的进程,这样每返回一个可用进程下标的时候,总是会
在进程起始位置搜寻,坏的情况下,要进行n次if查询。虽然安全序列的不同·对于整个银行家算法的实现
并无影响,但是我们始终哟注重时间效率。我在安全性检查方面借助了队列和栈。这虽然在增加空间代价,
但是可减少判断的次数。
(1)、栈思路:第一次不满足条件的进程入栈,先进去的进程最后出来 设计两个栈,一个是“等待栈”,用于存放第一次查询的时候不满足条件的进程,如果不满足要求,就
将该进程的下标压入等待栈中。那么循环下来之后,如果栈满的话,可以判定没有安全序列,如果有的话
就从等待栈中Pop一个进程,再次查询,如果不满足的话,我们在建立一个“副等待栈”,这个栈可以单独
设立,也可以起初的时候把进程就放在栈中,那么一轮循环下来,进程栈就空了,这时候就可以当作副等待
栈了,处理过程与等待栈的处理过程和思路一样。
(2)、队思路:第一次不满足条件的进程入队,先进去的进程先出来

这个思路就用队的方式来解决,代码没有来得及编写,大致与栈一致

代码实现:代码不精,乱七八糟,正在努力

:下面代码中有两个findindex函数,一个是用栈实现的,另一个是瞎写的。
当时看错算法内容了,以为是在安全性检查中,使不符合条件的进程等待。实际上无论安全性检查算法是怎么设计的,只要有安全序列就可以了。

#include<iostream>
using namespace std;
/*
*定义一个顺序栈
*/
typedef struct
{
	int *top;//栈顶指针
	int *base;//栈底指针
	int stacksize;//定义栈的大小
}SqStack;
/*
*初始化栈
*/
int initStack(SqStack &L,int n)
{//n代表栈的初始长度
	L.base = new int[n];
	if (!L.base)
		return 0;//如果创建栈失败,那么返回0
	L.top = L.base;//栈底与栈顶在同一位置,空栈
	L.stacksize = n;
	return 1;
}
/*
*Push 入栈,e代表被压入栈的内容
*/
int IsFull(SqStack L)
{
	if (L.top - L.base == 0)
		return 1;
	return 0;
}

//入栈
int Push(SqStack& L,int e)
{
	if (L.top-L.base==L.stacksize)
	{
		cout << "压栈失败,进程号:"<<e<< endl;
		return 0;//表示栈满
	}
	*L.top = e;
	L.top++;
	return 1;
}
//出栈
int Pop(SqStack& L, int &e)
{
	if (L.top - L.base == 0)
	{
		cout << "出栈失败,这是空栈" << endl;
		return 0;//这是空栈
	}
	L.top--;
	e = *L.top; 
	
	return 1;
}
//测试当前栈的实际长度
int getLength(SqStack L)
{
	return L.top - L.base;
}
#define Process_Num 5
#define Source_Num 3
int NUM = 0;
int Available[Source_Num] = { 3,3,2 };//this is available source_num
int Max[Process_Num][Source_Num] = {
{7,5,3},
{3,2,2},
{9,0,2},
{2,2,2},
{4,3,3}
};//this is the max source_num
int Allocation[Process_Num][Source_Num] =
{
{0,1,0},
{2,0,0},
{3,0,2},
{2,1,1},
{0,0,2}
};//this is the haved allocate source_num
int Need[Process_Num][Source_Num] =
{
{7,4,3},
{1,2,2},
{6,0,0},
{0,1,1},
{4,3,1}
};//这是当前进程所需要的资源的总数目
//int Request[Process_Num];//表示每个进程每次要申请访问的资源的数目
int Work[Source_Num];//在安全性检查算法中使用
int Finish[Process_Num];//安全性检查算法中使用,判断每个进程是否安全
int Resiger[Source_Num];//用于保存下标
/*******  函数区   *************/
int banker();//银行家算法
int isSafe();//安全性算法
int lh[Process_Num];//辅助数组
int findIndex();//在安全性检查算法中,寻找可以被分配资源的进程的下标
void show_one(int A[], int n);//打印一维函数所有值
int finish_true(int Finish[], int n);//判断安全性算法中的Finish函数是否全为true
int finish_false(int Finish[], int n);//判断安全性算法中的Finish函数是否全为false
int isEqual(int A[], int m, int B[]);//若对于任何 i B[i]>=A[i],return 1,否则返回0
void show_two();//显示函数
int find_zero(int A[], int m, int n);
int find_design(int A[], int n);
SqStack L1, L2, L;//L1:等待栈,L:存放进程栈,L2:进程栈的辅助栈
int main()
{

	if (banker() > -1)
		cout << "Successful,已经分配给进程。" << endl;
	int i, k;
	char m;
	do
	{
		k = banker();
		cout << endl;
		if (k >= 0 && finish_false(Need[k], Source_Num))
		{
			cout << "Successful 已经分配资源给进程 " << k << ",并且进程已完成并释放资源" << endl;
			for (int j = 0; j < Source_Num; j++)
			{
				Available[j] = Available[j] + Allocation[k][j];
				Allocation[k][j] = 0;
			}
			show_two();

		}
		else if (k >= 0 && !finish_false(Need[k], Source_Num))
		{
			cout << "Successful 已经分配资源给进程 " << k << ",但进程没有完成并释放资源" << endl;
			show_two();
		}
		else
			cout << "Default 分配资源给进程失败,请重新选择进程以及申请的资源" << endl;
		cout << "如果你想继续,请输入Y/y,否则输入N/n" << endl;
		cin >> m;
		if (m == 'Y' || m == 'y')
			i = 1;
		else if (m == 'N' || m == 'n')
			i = 0;
		cout << "******************************************" << endl;
	} while (i);
	return 0;
}
int  banker()
{//表示一次的进程进行资源申请,如果这次申请成功那么返回1,否则返回0
	int i, j, k, m;//i代表进程数,j代表资源地数目
	int Request[Source_Num];//作为临时数组
	show_two();
	cout << "正在检查T0时刻的安全性........" << endl;
	if (!isSafe())
	{
		cout << "T0时刻不安全,请重新分配......" << endl;
		exit(0);
	}
	cout << endl;
	printf("请输入请求资源的进程号 0--4,编号为:");
	cin >> i;
	m = i;
	cout << endl;
	printf("请输入进程 %d 要申请的各类资源的数目\n", i);
	cout << endl;
	for (j = 0; j < Source_Num; j++)
	{
		printf("第 %d 号资源申请数量:", j);
		cin >> Request[j];
		cout << endl;
	}
	cout << "Request请求资源数目为:" << endl;
	cout << "		A		B		C" << endl;
	show_one(Request, Source_Num);//打印数组
	cout << endl;
	/*判断该进程所申请资源的数量是否合理*/
	for (j = 0; j < Source_Num; j++)
		if (Request[j] > Need[i][j])
		{
			cout << "No:申请资源的数量超过进程最大需要的的数量" << endl;
			return -1;//如果申请错了,那么直接终止这次资源的申请
		}
	cout << "YES:申请资源的数量未超过进程最大需要的的数量" << endl;
	if (isEqual(Request, Source_Num, Available))
	{//表示request<Available
		for (j = 0; j < Source_Num; j++)
		{
			Available[j] = Available[j] - Request[j];
			Allocation[i][j] = Allocation[i][j] + Request[j];
			Need[i][j] = Need[i][j] - Request[j];
		}
		cout << "*************************************************" << endl;
		show_two();
		cout << "******************正在进行安全性检查*********************" << endl;
		if (!isSafe())
		{//表示此次分配不安全,就将已分配的资源恢复
			//表且还要将该进程等待
			for (j = 0; j < Source_Num; j++)
			{
				Available[j] = Available[j] + Request[j];
				Allocation[i][j] = Allocation[i][j] - Request[j];
				Need[i][j] = Need[i][j] + Request[j];
			}
			cout << "Sorry 当前申请不安全" << endl;
			return -1;
		}
		else
		{
			//show_two();
			return m;//表示此进程分配成功
		}
	}
	else
	{
		cout << "Default! 系统不能提供这么多资源" << endl;
		return -1;
	}


}
void show_one(int A[], int n)
{//这是一个打印出一维数组所有值的函数
	int i;
	if (n <= 0)
		return;
	cout << "		";
	for (i = 0; i < n; i++)
	{
		printf("%d		", A[i]);
	}
}
void show_two()
{
	int i, j;
	cout << "**************************************资源分配情况*******************************************" << endl;
	cout << "|	资源情况	work        allocation        need         Available   |" << endl;
	cout << "|	进程	      A  B  C        A  B  C        A   B   C	   A   B   C   |" << endl;
	for (i = 0; i < Process_Num; i++)
	{
		cout << "	" << i << "	    ";
		for (j = 0; j < Source_Num; j++)
		{
			cout << "  " << Max[i][j];
		}
		cout << "	   ";
		for (j = 0; j < Source_Num; j++)
		{
			cout << "  " << Allocation[i][j];
		}
		cout << "	 ";
		for (j = 0; j < Source_Num; j++)
		{
			cout << "   " << Need[i][j];
		}
		cout << "	";
		for (j = 0; j < Source_Num; j++)
		{
			if (i == 0)
				cout << "   " << Available[j];
		}
		cout << endl;
	}
}

int isSafe()
{
	int i;
	if (!initStack(L1, Process_Num))
	{
		cout << "Sorry!!! 等待栈L1初始化错误,程序即将退出" << endl;
		return -1;
	}
	if (!initStack(L, Process_Num))
	{
		cout << "Sorry!!! 进程栈L初始化错误,程序即将退出" << endl;
		return -1;
	}
	//为进程栈存放进程
	for (i = Process_Num - 1; i >= 0; i--)
		Push(L, i);//倒序压入进程栈中
	int j, k;//i 代表进程的计数器,j代表资源的计数器
	for (j = 0; j < Source_Num; j++)
		Work[j] = Available[j];
	for (i = 0; i < Process_Num; i++)
		Finish[i] = 0;
	cout << "安全序列:";
	while ((k = findIndex()) >= 0)
	{
		cout << k << "--->";
		for (j = 0; j < Source_Num; j++)
			Work[j] = Work[j] + Allocation[k][j];//释放资源
		Finish[k] = 1;
		if (finish_true(Finish, Process_Num))
		{//表示Finish全为true(1)
			delete[]L.base;
			delete[]L1.base;
			delete[]L2.base;
			return 1;//表示安全
		}
	}
	delete []L.base;
	delete []L1.base;
	delete []L2.base;
	return 0;//表示不安全

}
int findIndex()
{
	int i, j, e;
	while (!IsFull(L))
	{//这里是进程循环
		if (!Pop(L, i))
		{//从进程栈中取栈
			cout << "L栈出栈失败,进程号:" << i << endl;
			return -1;
		}
		j = 0;
		while (1)
		{//这里是资源循环,我们用j来判断资源能否满足进程i当j=Source_Num时,满足,小于时不满足
			if (Finish[i] == 0 && Need[i][j] <= Work[j])
				j++;
			else
			{
				//Pop(L, e);
				Push(L1,i);//压入栈中
				break;
			}
			if (j == Source_Num)
			{
				return i;
			}
		}
		if (j == Source_Num)
		{
			return i;
		}

	}
	//跳出上面while循环,表示进程栈L为空,那么此时我们需要检查等待栈的情况
	int n = getLength(L1);//nb表示等待栈的长度
	if (!initStack(L, n))
	{
		cout << "Sorry!!! 辅助栈L2初始化错误,程序即将退出" << endl;
		return -1;
	}
	while (!IsFull(L1) || getLength(L2) != n)
	{//此时等待栈中有进程在等待
		Pop(L1, i);//出栈并传递给i
		j = 0;
		while (1)
		{
			if (Finish[i] == 0 && Need[i][j] <= Work[j])
				j++;
			else
			{
				Push(L2, i);
			}
			
			if (j == Source_Num)
			{
				return i;
			}
		}
		if (j == Source_Num)
		{
			return i;
		}
		if (IsFull(L1) && getLength(L2) != n)
		{//此时表示,辅助栈未满而等待栈空闲
			Pop(L2, e);
			Push(L1, e);//这里作为一个调回
		}
	}
}
int isEqual(int A[], int m, int B[])
{//判断两个一维数组的的值是否相等,若A有一项大于B,返回0
//若B的任何一项都大于等于A中对应的,那么返回 1
	int i;
	for (i = 0; i < m; i++)
		if (A[i] > B[i])
			return 0;
	return 1;

}
int finish_true(int Finish[], int n)
{//判断finish数组的值是否全为 true,若是则返回 1,不是返回0
	int i;
	int k = 0;
	for (i = 0; i < n; i++)
	{
		if (Finish[i] == 1)
			k = k + 1;
		else
			k = k - 1;
	}
	if (k == 5)
		return 1;
	else
		return 0;
}
int finish_false(int Finish[], int n)
{//判断finish数组的值是否全为 true,若是则返回 1,不是返回0
	int i;
	int k = 0;
	for (i = 0; i < n; i++)
	{
		if (Finish[i] == 0)
			k = k + 1;
		else
			k = k - 1;
	}
	if (k == 5)
		return 1;
	else
		return 0;
}
/*
*findIndex @v2.0
*要求在某一个进程不能
*/
int findIndex_()
{//返回进程的编号
	int i, j, k, i_;
	i = 0;
	/*if (n == -1)//n就是上次的下标,如果为 -1表示这是第一次
		i = 0;
	else if (n == Process_Num - 1)
		i = 0;//表示最后一个完成,要开始第二轮的循环
	else if (n >= 0 || n < Process_Num - 1)
		i = n;*/
	i = find_design(Finish, Process_Num);
	while (i <= 4)
	{
		j = 0;//j作为资源的计数器,每一次都需要
		//k = find_design(lh, Process_Num);//k作为返回下
		while (1)
		{
			if (Finish[i] == 0 && Need[i][j] <= Work[j])
			{
				j++;
			}
			else {//如果当前按k不满足条件,置其在lh中为1
				//k = find_design(lh,Process_Num);
				//lh[i] = 1;
				break;//结束本次的循环
			}

			if (j == Source_Num)
			{
				return i;//返回进程的下标
			}
		}
		if (j == Source_Num)
		{
			return i;//返回进程的下标

		}
		i++;
	}
	return -1;
}
//在搜索下标函数中,如果在一次安全ixng算法A中
//进程i满足条件,那么下一次寻找时,开始的下标j要满足以下条件之一
//(1)j>i且j之后的进程没有被被释放
//(2)j=0
int find_design(int A[], int n)
{
	int i, j, index_r, num;
	index_r = -1;
	num = 0;


	for (i = 0; i < n; i++)
	{
		if (A[i] == 0 && A[n - 1] == 0)
		{
			index_r = i;
			if (find_zero(A, i, n - 1))
			{//表示I后面全为0,满足条件1
				break;
			}
		}
		if (A[i] == 0 && A[n - 1] == 1)
		{
			index_r = i;
			break;
		}

	}

	if (i == (Process_Num - 1) && A[i] == 0)
	{//表示已经搜寻一圈,到达最后一列
		for (j = 0; j < 3; j++)
			if (Need[i][j] <= Work[j])
				num++;
		if (num == 3)
		{
			//表示最后一个进程安全
			return i;//可以直接返回
		}
		else
		{//最后一个进程不安全,并且从头开始没有全为0的,那么从0开始,见到一个0
			//就返回
			/*if (!find_zero(A, 0, n - 1))
			{
				for (i = 0; i < n; i++)
					if (A[i] == 0)
						return i;
			}
			else*/
			return 0;

		}
	}

	if (index_r == -1)
	{
		cout << "没有找到,不满足条件1" << endl;
		return -1;
	}
	else
		return index_r;
}
int find_zero(int A[], int m, int n)
{//判断A数组,[m,n]之间内有没有全0,
	//如果有,返回 1.否则,返回 0;
	int i, j;
	j = 0;
	for (i = m + 1; i <= n; i++)
	{
		if (A[i] == 0)
			j++;
		else
			j--;

	}
	if (j != (n - m))
		return 0;
	else
		return 1;
}
银行家算法是避免死锁的一种重要方法,本程序用java编程语言对其进行了实现。 当用户申请一组资源时,系统必须做出判断,如果把这些资源分出去,系统是否还处于安全状态。 若是,就可以分出这些资源;否则,该申请暂不予满足。 1.数据结构 假设有M个进程N类资源,则有如下数据结构: MAX[M*N] M个进程对N类资源的最大需求量 AVAILABLE[N] 系统可用资源数 ALLOCATION[M*N] M个进程已经得到N类资源的资源量 NEED[M*N] M个进程还需要N类资源的资源量 2.银行家算法 设进程I提出请求Request[N],则银行家算法按如下规则进行判断。 (1)如果Request[N]<=NEED[I,N],则转(2);否则,出错。 (2)如果Request[N]<=AVAILABLE,则转(3);否则,出错。 (3)系统试探分配资源,修改相关数据: AVAILABLE=AVAILABLE-REQUEST ALLOCATION=ALLOCATION+REQUEST NEED=NEED-REQUEST (4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。 3.安全性检查 (1)设置两个工作向量WORK=AVAILABLE;FINISH[M]=FALSE (2)从进程集合中找到一个满足下述条件的进程, FINISH[i]=FALSE NEED<=WORK 如找到,执行(3);否则,执行(4) (3)设进程获得资源,可顺利执行,直至完成,从而释放资源。 WORK=WORK+ALLOCATION FINISH=TRUE GO TO 2 (4)如所有的进程Finish[M]=true,则表示安全;否则系统不安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值