对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