【计算机操作系统】银行家算法和安全性算法的 C++ 实现(附源码) - Go语言中文社区

【计算机操作系统】银行家算法和安全性算法的 C++ 实现(附源码)


一、实验目的

  用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。因为源码中我对一些关键步骤的注释已经比较清晰了,所以在本文中不会再对每一个细节都进行分析,只分析整体的代码结构和所使用到的设计模式。

  博客内所有文章均为 原创,所有示意图均为 原创,若转载请附原文链接。

二、实验内容

2.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 。Allocationi 表示进程i的分配向量,有矩阵 Allocation 的第 i 行构成。

  • 4.需求矩阵 Need,这是一个 n×m 的矩阵,用以表示每个进程还需要的各类资源的数目。如果Need(i,j) = k,表示进程i还需要 Rj 类资源 k 个,才能完成其任务。Needi 表示进程i的需求向量,由矩阵 Need 的第 i 行构成。

  • 上述三个矩阵间存在关系:Need(i,j) = Max(i,j) - Allocation(i,j);

2.2 银行家算法

  设 Requesti 是进程 Pi 的请求向量,如果 Requesti[j] = K,表示进程 Pi 需要 K 个 Pj 类型的资源。当 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 + Requesti[j];
    Need[i,j] = Need[i,j] - Requesti[j];
  • (4)系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程 Pi,以完成本次分配;否则,将本次的试探性分配作废,恢复原来的资源分配状态,让进程 Pi 等待。

2.3 安全性算法

  • 1.设置两个向量。
    Work:它表示系统可提供给进程继续运行的各类资源数目,它包含m个元素,开始执行安全性算法时,Work = Available。
    Finish:它表示系统是否有足够的资源分配给进程,使之运行完成,开始Finish(i)=false;当有足够资源分配给进程Pi时,令Finish(i)=true;

  • 2.从进程集合中找到一个能满足下述条件的进程。
    Finish(i) == false;
    Need i ≤ work;
    如找到则执行步骤3;否则,执行步骤4;

  • 3.当进程 Pi 获得资源后,可顺利执行直到完成,并释放出分配给它的资源,故应执行
    Work = work + Allocation i
    Finish(i) = true;转向步骤2;

  • 4.若所有进程的 Finish(i) 都为true,则表示系统处于安全状态;否则,系统处于不安全状态。

三、流程图

3.1 单道批处理系统的作业调度

在这里插入图片描述

四、代码实现

#include <iostream>
#include <vector>

typedef std::vector<int> Resource;
typedef std::vector<int> * ResourcePtr;
typedef std::vector<std::vector<int>> Resources;
typedef std::vector<std::vector<int>> * ResourcesPtr;

class BankerAlgorithm
{
public:
	BankerAlgorithm()
	{
		/*
		process_num_ = process_num;
		resource_num_ = resource_num;
		*/

		// should input by  user
		//available_ = new std::vector<int>(resource_num, 0);
		/*
		(*available_)[0] = 3;
		(*available_)[1] = 3;
		(*available_)[2] = 2;
		*/

		//allocation_ = createResourceArray(process_num, resource_num);
		//need_ = createResourceArray(process_num, resource_num);

		/*
		(*need_)[0][0] = 7; (*need_)[0][1] = 4; (*need_)[0][2] = 3;
		(*need_)[1][0] = 1; (*need_)[1][1] = 2; (*need_)[1][2] = 2;
		(*need_)[2][0] = 6; (*need_)[2][1] = 0; (*need_)[2][2] = 0;
		(*need_)[3][0] = 0; (*need_)[3][1] = 1; (*need_)[3][2] = 1;
		(*need_)[4][0] = 4; (*need_)[4][1] = 3; (*need_)[4][2] = 1;

		(*allocation_)[0][0] = 0; (*allocation_)[0][1] = 1; (*allocation_)[0][2] = 0;
		(*allocation_)[1][0] = 2; (*allocation_)[1][1] = 0; (*allocation_)[1][2] = 0;
		(*allocation_)[2][0] = 3; (*allocation_)[2][1] = 0; (*allocation_)[2][2] = 2;
		(*allocation_)[3][0] = 2; (*allocation_)[3][1] = 1; (*allocation_)[3][2] = 1;
		(*allocation_)[4][0] = 0; (*allocation_)[4][1] = 0; (*allocation_)[4][2] = 2;
		*/
	}

	inline ResourcesPtr createResourceArray(int row_num, int col_num)
	{
		return new std::vector<std::vector<int>>(row_num, std::vector<int>(col_num, 0));
	}

	inline ResourcesPtr copyResourceArray(ResourcesPtr ori)
	{
		int col_num = (*ori)[0].size();
		int row_num = (*ori).size();
		ResourcesPtr res = createResourceArray(row_num, col_num);
		for (int i = 0; i < row_num; ++i)
			for (int j = 0; j < col_num; ++j)
				(*res)[i][j] = (*ori)[i][j];
		return res;
	}

	bool inputInitData()
	{
		std::cout << "please input process num and resource num: " << std::endl;
		std::cin >> process_num_ >> resource_num_;

		// allocate memory for struct
		available_ = new std::vector<int>(resource_num_, 0);
		allocation_ = createResourceArray(process_num_, resource_num_);
		need_ = createResourceArray(process_num_, resource_num_);

		std::cout << "please input init resource: " << std::endl;
		for (int i = 0; i < resource_num_; ++i)
			std::cin >> (*available_)[i];

		std::cout << "please input max matrix: " << std::endl;
		ResourcesPtr max = createResourceArray(process_num_, resource_num_);
		bool inputSuccess = true;
		do {
			inputSuccess = true;
			for (int i = 0; i < process_num_; ++i)
			{
				for (int j = 0; j < resource_num_; ++j)
				{
					std::cin >> (*max)[i][j];
					if ((*max)[i][j] > (*available_)[j])
					{
						inputSuccess = false;
						max->clear();
						std::cout << "max matrix is illegal, please reinput max matrix: " << std::endl;
						break;
					}
				}
			}
		} while (!inputSuccess);


		std::cout << "please input allocation matrix: " << std::endl;
		for (int i = 0; i < process_num_; ++i)
		{
			for (int j = 0; j < resource_num_; ++j)
			{
				std::cin >> (*allocation_)[i][j];
				(*need_)[i][j] = (*max)[i][j] - (*allocation_)[i][j];
				(*available_)[j] -= (*allocation_)[i][j];
			}
		}
		std::cout << "current available resource: [";
		for (int num : *available_)
			std::cout << num << " ";
		std::cout << "]" << std::endl;

		std::vector<int> * req = new std::vector<int>(resource_num_, 0);
		if (!bankerAlgorithm(-1, req))
		{
			std::cout << "init fail, data is illegal!" << std::endl;
		}

		bool quit = false;
		while (!quit)
		{
			std::cout << "please input request process: " << std::endl;
			int pid = -1;
			std::cin >> pid;

			std::cout << "please input request resource: " << std::endl;
			for (int i = 0; i < resource_num_; ++i)
				std::cin >> (*req)[i];

			// do allocate.
			bankerAlgorithm(pid, req);
		}
	}

	inline bool allocateResourcesForProcess(int pid, ResourcePtr request)
	{
		return bankerAlgorithm(pid, request);
	}

	bool bankerAlgorithm(int pid, ResourcePtr request)
	{
		for (int i = 0; pid != -1 && i < (*request).size(); ++i)
		{
			if ((*request)[i] > (*need_)[pid][i])
			{
				std::cout << "[ERROR] request Resource more than need ResourcePtr." << std::endl;
				return false;
			}
			else if ((*request)[i] > (*available_)[i])
			{
				std::cout << "[ERROR] request Resource more than available ResourcePtr." << std::endl;
				return false;
			}
		}

		// Here the copied value is passed
		if (securityAlgorithm(pid, *available_, *request, *need_, *allocation_))
		{
			std::cout << "[INFO] securityAlgorithm true" << std::endl;

			// Really allocate resources to process
			for (int i = 0; pid != -1 && i < (*request).size(); ++i)
			{
				(*available_)[i] -= (*request)[i];
				(*allocation_)[pid][i] += (*request)[i];
				(*need_)[pid][i] -= (*request)[i];
			}
			// Debug
			printResources();
			return true;
		}
		else
		{
			std::cout << "[INFO] securityAlgorithm false" << std::endl;
			// Don't allocate resources to process
			// Debug
			printResources();
			return false;
		}
	}

	bool securityAlgorithm(int pid, Resource available, Resource request, Resources need, Resources allocation)
	{
		if (pid != -1)
		{
			for (int i = 0; i < request.size(); ++i)
			{
				available[i] -= request[i];
				allocation[pid][i] += request[i];
				need[pid][i] -= request[i];
			}
		}

		Resource work(available);
		std::vector<bool> finish(allocation.size(), false);

		while ((pid = getUsableProcessForSecurityAlgorithm(finish, work, need)) != -1)
		{
			for (int i = 0; i < work.size(); ++i)
				work[i] += allocation[pid][i];
			finish[pid] = true;

			std::cout << "[INFO] process " << pid << " finish true, work: [";
			for (int num : work)
				std::cout << num << " ";
			std::cout << "]" << std::endl;

		}

		for (bool b : finish)
			if (!b) return false;
		return true;
	}

	// return pid
	int getUsableProcessForSecurityAlgorithm(std::vector<bool> finish, Resource work, Resources need)
	{
		for (int pid = 0; pid < finish.size(); ++pid)
		{
			if (!finish[pid])
			{
				bool canUse = true;
				for (int i = 0; i < work.size(); ++i)
				{
					if (need[pid][i] > work[i])
					{
						canUse = false;
						break;
					}
				}
				if (canUse) return pid;
			}
		}
		return -1;
	}

	bool printResources()
	{
		std::cout << "available: " << std::endl;
		for (int num : *available_)
			std::cout << num << " ";
		std::cout << std::endl << std::endl;

		std::cout << "allocation: " << std::endl;
		printResource(allocation_);
		std::cout << std::endl;

		std::cout << "need: " << std::endl;
		printResource(need_);
		std::cout << std::endl;
	}

	bool printResource(ResourcesPtr ResourcesPtr)
	{
		for (std::vector<int> vec : *ResourcesPtr)
		{
			for (int num : vec)
				std::cout << num << " ";
			std::cout << std::endl;
		}
		return true;
	}

private:
	int process_num_;
	int resource_num_;

	ResourcePtr available_;
	ResourcesPtr allocation_;
	ResourcesPtr need_;
};

五、运行结果

5.1 初始化

在这里插入图片描述

5.2 验证初始化状态的安全性

在这里插入图片描述

5.3 进程1请求资源 1 0 2 并通过安全性检查,分配给它资源

在这里插入图片描述

5.4 进程4请求资源 3 3 0 并因为其请求资源大于Available资源,因此让进程4等待

在这里插入图片描述

5.5 进程0请求资源 0 2 0 并因为进行安全性检查时不存在安全序列,因此不分配资源

在这里插入图片描述

5.6 进程0请求资源 0 1 0 并因为符合安全性检查,存在安全队列,因此分配资源

在这里插入图片描述

六、结尾

  如果本文描述的内容或使用的代码存在任何问题,请及时联系我或在本篇文章的下面进行评论,我会本着对每一位学技术同学的负责态度立即修改。在后续还会有三篇计算机操作系统的算法 C++ 复现博文,如果感兴趣可以关注我。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_40697071/article/details/106723227
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢