【操作系统实践】银行家算法的设计与实现

对I/O系统中死锁问题求解的主要方法是银行家算法,单种资源的银行家算法和多种资源的银行家算法的解决思路一致,要求设计实现多种资源的银行家算法,并要求所涉及的模型最少能够满足如下要求:
(1)程序能够根据进程的请求进行判断,给出系统是否安全的提示,如果安全,要求能够显示一组进程执行的安全序列;
(2)能够根据需要,显示当前系统中各种资源的分配情况。

银行家算法(Banker's Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

                                                                                                         ------摘自百度百科

在图3.15中可以看到两个矩阵。左边的矩阵显示出对5个进程分别已分配的各种资源数,右边的矩阵则显示了使各进程运行结束还需要的各种资源数。与单一资源的情况一样,各进程在执行前给出其所需的全部资源量,所以系统的每一步都可以计算出右边的矩阵。
图3.15最右边的3个向量分别表示总资源E、已分配资源Р和剩余资源A。由E可知系统中共有6台磁带机、3台绘图仪、4台打印机和2台CD-ROM。由P可知当前已分配了5台磁带机、3台绘图仪、2台打印机和2台CD-ROM。该向量可通过将左边矩阵的各列相加得到,剩余资源向量可通过从资源总数中减去已分配资源数得到。
检查一个状态是否安全的算法描述如下:

1.查找右边矩阵中是否有一行,其未被满足的资源数均小于或等于A。
如果不存在这样的行,
则系统将死锁,因为任何进程都无法运行结束。
2.若找到这样一行,则可以假设它获得所需的资源并运行结束,将该进程标记为结束,并将资源加到向量A上。
3.重复以上两步,直到所有的进程都标记为结束。若能达到这种状态,则初始状态是安全的;或者直到发生死锁,则初始状态是不安全的。

                                                    ----------图及图后文字均摘自《操作系统实践与设计第三版上册》

 基本上就是实现了一个banker类,可以管理总资源、已分配资源,处理待分配资源,同时,还可以展示目前的资源分配情况,可以给出安全序列。多的都是废话,代码填在下面,本人也是刚刚入门,评论区欢迎发表意见。

#include<iostream>
#include<vector>
#include<unordered_map>
#include<fstream>
using namespace std;
//本程序中假设进程需要的资源,机器全具有
//假设整个系统共管理n种资源
struct process_ {
	string m_name;
	//假设进程不会重名
	vector<int> m_need;
	int m_need_kinds;
	process_(string a, int n, vector<int>& c) {
		m_name = a;
		m_need_kinds = n;
		for (int i = 0; i < m_need_kinds; i++) {
			m_need.push_back(c[i]);
		}
	}
};
class banker {
private:
	int m_have_kinds_int;//资源种类
	vector<int> m_have_resourse_veci;//拥有的全部资源
	vector<int> m_give_sum_veci;//已分配的资源
	vector<process_> m_give;//分配资源的进程
	vector<process_> m_to_deal;//仍需要的进程
	int m_give_process_int;//已经申请过资源的进程数
	string m_saf_array_str;
	unordered_map<string, int> m_process_hash;//储存已经申请过资源的进程,用哈希保存下标
public:
	//构造函数
	banker(int n, vector<int> b,vector<process_> c) {
		m_have_kinds_int = n;
		m_have_resourse_veci.resize(m_have_kinds_int);
		m_give_sum_veci.resize(m_have_kinds_int);
		for (int i = 0; i < m_have_kinds_int; i++) {
			m_have_resourse_veci[i] = b[i];
		}
		cout << "现在进行初始化,按照已分配矩阵写入分配数据" << endl;
		for (int i = 0; i < c.size(); i++) {
			give(c[i]);
		}
		m_saf_array_str.clear();
	}
	//给出已分配资源序列
	void show_give() {
		if (m_give_process_int == 0) {
			cout << "目前未给任何进程分配资源" << endl;
			return;
		}
		cout << "已分配资源如下:" << endl;
		cout << "进程名";
		for (int i = 0; i < m_have_kinds_int; i++) {
			cout << "资源" << i<<' ';
		}
		cout << endl;
		for (int i = 0; i < m_give.size(); i++) {
			cout << m_give[i].m_name << "      ";
			for (int j = 0; j < m_give[i].m_need_kinds; j++) {
				cout << m_give[i].m_need[j] << "      ";
			}
			cout << endl;
		}
	}
	//检查是否安全
	bool check(process_& a) {
		for (int i = 0; i < m_have_kinds_int; i++) {
			if (m_give_sum_veci[i] + a.m_need[i] > m_have_resourse_veci[i])return false;
		}
		return true;
	}
	//分配资源
	void give(process_& a) {
		if (m_process_hash.find(a.m_name) == m_process_hash.end()) {
			//说明这个进程以前未申请过
			m_process_hash.insert({a.m_name, m_give_process_int});
			m_give_process_int++;
			m_give.push_back(a);
			for (int i = 0; i < m_have_kinds_int; i++) {
				m_give_sum_veci[i] += a.m_need[i];
			}
		}
		else {
			int temp = m_process_hash.find(a.m_name)->second;
			for (int i = 0; i < m_have_kinds_int; i++) {
				m_give[temp].m_need[i] += a.m_need[i];
			}
			for (int i = 0; i < m_have_kinds_int; i++) {
				m_give_sum_veci[i] += a.m_need[i];
			}
		}
		cout << "现在,为进程" << a.m_name << "分配了资源" << endl;
		m_saf_array_str += a.m_name;
		m_saf_array_str += ' ';
	}
	//给出安全序列
	void show_array() {
		cout << "安全序列为:" ;
		cout << endl << m_saf_array_str << endl;
	}
	//释放资源
	void delete_res(int i) {
		//清除哈希的痕迹
		unordered_map<string, int>::iterator it1 = m_process_hash.begin();
		for (int k = 0; k < m_give_process_int; k++) {
			if (it1->second == i)break;
			else it1++;
		}
		m_process_hash.erase(it1);
		//减小一个进程数
		m_give_process_int--;
		//把资源都拿回来
		for (int j = 0; j < m_have_kinds_int; j++) {
			m_give_sum_veci[j] -= m_give[i].m_need[j];
			m_have_resourse_veci[j] += m_give[i].m_need[j];
			m_give[i].m_need[j] = 0;
		}
		//值得注意的是,为了使哈希表可以继续使用,仅释放资源,但是并不在m_give中删去这个资源
		/*vector<process_>::iterator it = m_give.begin() + i;
		m_give.erase(it);*/
	}
	//处理资源申请
	void deal_apply(vector<process_> a) {
		cout << "现在,开始处理待分配序列" << endl;
		int flag = 0;
		do {
			flag = 0;
			for (int i = 0; i < a.size(); i++) {
				if (check(a[i])) {
					give(a[i]);
					//分配完展示一下
					show_give();
					delete_res(m_process_hash.find(a[i].m_name)->second);
					vector<process_>::iterator it = a.begin() + i;
					a.erase(it);
					m_give_process_int++;
					flag++;
					//下面两行代码代表了不同的思路,分别是找到一个可分配的,给他分配并释放之后,是往下找还是继续从头找,结果均正确
					//i--;
					break;
				}
			}
		} while (flag != 0);
		if (a.size() != 0)cout << "处于不安全状态,无法继续分配" << endl;
		else cout << "分配完成" << endl;
	}
	
};
int main() {
	//测试用例输入区
	int use_n = 4;//总资源种类
	vector<int> E = { 6,3,4,2 };//可用资源
	vector<process_> in1;//已分配资源
	vector<process_> in2;//待处理申请
	ifstream use("test.txt", ios_base::in);
	int n1,n2 = 0;
	use >> n1;
	for (int i = 0; i < n1; i++) {
		string temp;
		vector<int> need;
		use >> temp;
		for (int i = 0; i < use_n; i++) {
			int num;
			use >> num;
			need.push_back(num);
		}
		in1.push_back(process_(temp, use_n, need));
	}
	use >> n2;
	for (int i = 0; i < n1; i++) {
		string temp;
		vector<int> need;
		use >> temp;
		for (int i = 0; i < use_n; i++) {
			int num;
			use >> num;
			need.push_back(num);
		}
		in2.push_back(process_(temp, use_n, need));
	}
	banker test(use_n, E, in1);
	test.show_give();
	test.deal_apply(in2);
	test.show_array();
	return 0;
}

这里给个测试用例:需要装进一个txt文件使用

5
A 3 0 1 1
B 0 1 0 0
C 1 1 1 0
D 1 1 0 1
E 0 0 0 0
5
A 1 1 0 0
B 0 1 1 2
C 3 1 0 0
D 0 0 1 0
E 2 1 1 0

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值