admin 管理员组

文章数量: 887016

一.实验目的:

        银行家算法是一种最有代表性的避免死锁的算法。通过编写一个模拟动态资源分配的银行家算法程序,进一步深入理解死锁、产生死锁的必要条件、安全状态等重要概念,并掌握避免死锁的具体实施方法。

二.实验要求:

        程序可以针对不同进程的请求进行判断,并决定是否满足其需求。算法程序需要设计合理的数据结构,对资源情况、进程相关数据进行存储。

三.  实验内容:

        在避免死锁方法中允许进程动态地申请资源,用户请求分配资源时,首先对用户提出的请求进行合法性检查,若不存在请求的资源大于可利用的资源、可分配的资源的情况,则请求合法,进行预分配。系统在进行资源分配之前,应先计算此次分配资源的安全性;若分配不会导致系统进入不安全状态,则分配,否则等待。

四.算法描述:

1. 银行家算法中的数据结构 

   (1)可利用资源向量Available

       这是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变,如果Available[j]=K,则表示系统中现有Rj  类资源的最大数目为K。

   (2)最大需求矩阵Max

        这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj 类资源的最大数目为K。

    (3)分配矩阵Allocation

        这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj 类资源的数目为K。

    (4)需求矩阵Need。

        这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj 类资源K个方能完成其任务。  

        上述三个矩阵间存在下述关系:

        Need[i,j]=Max[i,j]-Allocation[i,j] 

2. 银行家算法

        设Requesti是进程Pi 的请求向量,如果Requesti[j]=K,表示进程Pi 需要K个Rj 类型的资源。当Pi 发出资源请求后,系统按下述步骤进行检查:

        (1)如果Requesti[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布最大值。

        (2)如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源, Pi须等待。 

        (3)系统试探着把资源分配给进程Pi ,并修改下面数据结构中的数值

                Available[j]=Available[j]-Requesti[j];

                Allocation[i,j]=Allocation[i,j]+Requesti[j];  

                Need[i,j]=Need[i,j]-Requesti[j];

          (4)系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi ,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi 等待。

3. 安全性算法

(1)设置两个向量:

        工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work=Available;

        Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false; 当有足够资源分配给进程时, 再令Finish[i]=true。 

(2)从进程集合中找到一个能满足下述条件的进程:       

        Finish[i]=false;

        Need[i,j]≤Work[j];

        若找到,执行 (3),否则,执行 (4)

(3)当进程Pi 获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

        Work[j]= Work[i]+Allocation[i,j];

        Finish[i]=true;

        go to step 2;

(4)如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态;

五.运行结果与分析:

        运行程序,首先需要输入进程的数目和资源的数目,每个进程最多所需的各资源数、已分配的各资源数和各个资源现有的数目,运行及输入情况如下图所示:

图1 输入初始数据

        在分配资源之前,首先会判断当前初始状态是否为安全状态,若处于安全状态,则提示系统是安全的,并输出安全序列,允许资源分配。反之,若处于不安全状态,则不允许后续的资源分配。

图2 判断初始状态

        在申请分配资源之前,首先将系统可用的资源数、各进程最多需要的资源数、各进程已经得到的资源、各进程还需要的资源量输出。各进程还需要的资源量等于最多需要的资源数减各进程已经得到的资源数。

图3 输出基本数据

        开始进行分配资源,首先输入要申请的进程号,输入进程所请求的各资源数;根据申请进行安全性检查,如果处于安全状态,则允许分配,并输出安全序列。分配完成后如果想要再次分配,输入y/Y,否则输入其它符号:

图4 申请分配资源结果图

        输入y再次请求分配资源,同样首先输出当前系统可用的资源数、各进程最多需要的资源数、各进程已经得到的资源、各进程还需要的资源量输出。

图5 再次申请分配资源

        输入申请3进程,但由于此时3进程需要资源数小于申请的资源数,因此提示输入的资源请求数超过进程数需求量,并重新输入。结果图如下所示:

图6 申请分配资源失败图1

        若所申请的资源数大于系统可分配的资源数,则会提示输入的资源请求数超过系统当前资源拥有数,并重新输入:

图7 申请分配资源失败图2

        再次申请分配资源,申请分配给进程0资源数为1,0,0;此时系统是安全的,成功分配。同时输入n,结束资源分配。结果图如下所示:

图8 再次申请分配资源图

六.源程序:

#include<iostream>
using namespace std;
const int Max_process = 50;//最大进程数
const int Max_source = 50;//最大资源数


class bank
{
private:
	int available[Max_source];//可用资源数
	int max[Max_process][Max_source];//最大需求
	int allocation[Max_process][Max_source];//已分配资源数
	int need[Max_process][Max_source];//还需资源数
	int request[Max_process][Max_source];//进程需要资源数
	bool finish[Max_process];//判断系统是否有足够的资源分配
	int p[Max_process];//记录序列
	int m;//用来表示进程
	int n;//表示资源

public:
	void Init();//完成对变量的初始化
	bool Safe();//安全检测算法
	void Banker();//银行家算法
	void Display(int, int);//显示进程与资源状态

};


void bank::Init()
{
	cout << "请输入进程的数目:";
	cin >> m;

	cout << "请输入资源的数目:";
	cin >> n;

	cout << "请输入每个进程最多所需的各资源数,按照" << m << 'X' << n << "矩阵格式输入" << endl;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			cin >> max[i][j];

	cout << "请输入每个进程已分配的各资源数,按照" << m << 'X' << n << "矩阵格式输入" << endl;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
		{
			cin >> allocation[i][j];已分配资源数
			need[i][j] = max[i][j] - allocation[i][j];
			if (need[i][j] < 0)
			{
				cout << "你输入的第" << i + 1 << "个进程的第" << j + 1 << "个资源数有问题!\n请重新输入!";
				j--;//忽略这个资源数
				continue;//跳出本次循环
			}
		}


	cout << "请输入各个资源现有的数目" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> available[i];可用资源数
	}

}


//m表示进程,n表示资源
void bank::Display(int n, int m)
{
	cout << endl << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

	cout << "系统可用的资源数为:";
	for (int i = 0; i < n; i++)
	{
		cout << available[i] << " ";
	}

	cout << endl << "各进程最多需要的资源数:" << endl;
	for (int i = 0; i < m; i++)
	{
		cout << "P" << i << ":";
		for (int j = 0; j < n; j++)
		{
			cout << " " << max[i][j];
		}
		cout << endl;
	}

	cout << endl << "各进程已经得到的资源:" << endl;
	for (int i = 0; i < m; i++)
	{
		cout << "P" << i << ":";
		for (int j = 0; j < n; j++)
		{
			cout << " " << allocation[i][j];
		}
		cout << endl;
	}

	cout << endl << "各进程还需要的资源量:" << endl;
	for (int i = 0; i < m; i++)
	{
		cout << "P" << i << ":";
		for (int j = 0; j < n; j++)
			cout << " " << need[i][j];
		cout << endl;
	}

	cout << endl << endl;
}


void bank::Banker()
{
	int num_process, flag = 0;//num_process表示资源进程号
	char again;//键盘录入一个字符用于判断是否继续请求资源
	while (1)
	{
		Display(n, m);
		cout << endl;
		/*请求资源*/
		while (true)
		{
			cout << "请输入要申请的进程号:";
			cin >> num_process;
			if (num_process > m)
			{
				cout << "没有该进程,请重新输入" << endl;
				continue;
			}
			cout << "请输入进程所请求的各资源数:" ;
			for (int i = 0; i < n; i++)
				cin >> request[num_process][i];
			for (int i = 0; i < n; i++)
			{
				if (request[num_process][i] > need[num_process][i])
				{
					cout << "你输入的资源请求数超过进程数需求量!请重新输入" << endl;
					continue;
				}
				if (request[num_process][i] > available[i])
				{
					cout << "你输入的资源请求数超过系统当前资源拥有数!" << endl;
					break;
				}
			}
			break;
		}

		/*上述是资源请求不合理的情况,下面是资源请求合理时则执行银行家算法*/

		for (int i = 0; i < n; i++)
		{
			available[i] -= request[num_process][i];//可用资源减去成功申请的
			allocation[num_process][i] += request[num_process][i];//已分配资源加上成功申请的
			need[num_process][i] -= request[num_process][i];//进程还需要的减去成功申请的
		}

		/*判断分配申请资源后系统是否安全,如果不安全则将申请过的资源还给系统*/
		if (Safe())//安全性算法
			cout << "同意分配请求!"<<endl;
		else
		{
			cout << "你的请求被拒绝! !!" << endl;
			/*进行向系统还回资源操作*/
			for (int i = 0; i < n; i++)
			{
				available[i] += request[num_process][i];
				allocation[num_process][i] -= request[num_process][i];
				need[num_process][i] += request[num_process][i];
			}
		}
		/*判断是否继续申请*/
		cout << "你还想再次请求分配吗?是请按Y/y,否请按其他键!" << endl;
		cin >> again;
		if (again == 'Y' || again == 'y')
			continue;
		break;
	}
}

m表示进程,n表示资源
bool bank::Safe()
{
	int l = 0, j, i;
	int work[Max_source];//工作向量,系统可提供给进程继续运行所需各类资源数
	/*对work数组进行初始化,初始化时和avilable可用资源数数组相同*/
	for (int i = 0; i < n; i++)
		work[i] = available[i];
	/*对finish数组(判断系统是否有足够的资源分配)初始化全为false*/
	for (int i = 0; i < m; i++)
		finish[i] = false;
	for (int i = 0; i < m; i++)
	{
		if (finish[i] == true)
			continue;
		else
		{
			for (j = 0; j < n; j++)
			{
				if (need[i][j] > work[j])
					break;
			}
			if (j == n)
			{
				finish[i] = true;
				for (int k = 0; k < n; k++)
					work[k] += allocation[i][k];  //已分配+work(可分配)
				p[l++] = i;//记录进程号
				i = -1;保证每次查询均从第一个进程开始
			}
			else
				continue;
		}
	}

	if (l == m)//进程数
	{
		cout << "系统是安全的" << endl;
		cout << "安全序列:" << endl;
		for (int i = 0; i < l; i++)
		{
			cout << p[i];
			if (i != l - 1)
				cout << "-->";
		}
		cout << endl << endl;
		return true;
	}

}


int main()
{
	cout << "------------------------------------------------" << endl;
	cout << endl << endl;
	cout << "                银行家算法" << endl;
	cout << endl << endl;
	cout << "------------------------------------------------" << endl;
	bank peter;
	peter.Init();
	peter.Safe();
	peter.Banker();
	return 0;
}

本文标签: 银行家 算法 操作系统