1230: 银行家算法
时间限制: 1 Sec 内存限制: 128 MB Special Judge
提交: 306 解决: 124
[提交] [状态] [讨论版] [命题人:newworldblues]
题目描述
一、实验目的
1、加深理解银行家算法及相关概念。
2、掌握进程申请资源时的安全性检查算法。
3、能看懂资源分配表(教材p122图3-5)。
二、实验原理
1、银行家算法原为银行系统设计,以确保银行在发放现金贷款时,不会发生不能满足所有客户需求的情况。银行家算法可以帮助操作系统避免死锁(将客户比作进程,贷款单位比作资源,银行家比作操作系统)。
2、为实现银行家算法,每个进程必须事先声明自己需要的每种资源类型的最大数目。当进程请求资源时,系统必须确保该进程所拥有的资源数不超过它事先声明最大资源数,同时确保资源请求量不超过当前可用资源量。若两项均满足则执行安全性检查算法。
3、安全性检查算法用于检查系统进行资源分配后是否安全,若安全,系统才可执行此次分配,否则不执行此次分配。
4、安全性检查算法:在系统试分配资源后,算法从现有进程列表中寻找出一个可执行进程,回收该进程占用的资源,并寻找下一个可执行进程。若某种执行顺序能够使得所有进程能依次执行,则产生一个安全执行序列,并允许此次资源分配。若进程无法全部执行(无法找到一个安全序列),则本次资源分配将导致系统进入不安全状态,故本次资源请求失败。
三、实验要求
1、用C++语言编写程序,实现银行家算法。
2、main 函数及部分代码已编写如下,只需由你编写 banker 函数并提交。
#include <iostream>
#include <vector>
using namespace std;
void banker(vector<int> &R, vector<vector<int> > &A, vector<vector<int> > &C, vector<vector<int> > &reqestSequence);
int main()
{
int n, m; // 系统中有 n 个进程、m 种不同类型的资源
int N; // 进程请求资源的次数
int i, j;
cin >> n; // 输入进程数量
cin >> m; // 输入资源类型数
vector<int> R(m); // R 向量表示系统中每种资源的的总量
for (i = 0; i < m; i++) // 对 m 种资源,输入每种资源的总量,保存到向量 R 中
{
cin >> R[i];
}
vector<vector<int> > C(n, vector<int>(m)); // C 为 Claim 矩阵,即最大需求矩阵,教材上称 Max 矩阵
for (i = 0; i < n; i++) // 输入 C 矩阵
{
for (j = 0; j < m; j++)
{
cin >> C[i][j];
}
}
vector<vector<int> > A(n, vector<int>(m)); // A 为 Allocation 矩阵,即分配矩阵
for (i = 0; i < n; i++) // 输入 A 矩阵
{
for (j = 0; j < m; j++)
{
cin >> A[i][j];
}
}
////////////////////////////////////////////////////////////////////////////////
// 欲针对当前状态做 N 次资源请求测试,故这里一次性输入 N 次资源请求,每次资源请
// 求需要输入 m+1 个整数:第 0 个整数表示申请资源的进程号(取值范围:0 至 n-1);
// 第 1 至 m 个整数分别表示当前状态下,该进程对 m 种资源的申请数量。
cin >> N; // 输入进程请求资源的次数
vector<vector<int> > reqestSequence(N, vector<int>(m+1));
for (i = 0; i < N; i++)
{
for (j = 0; j <= m; j++)
{
cin >> reqestSequence[i][j];
}
}
//
////////////////////////////////////////////////////////////////////////////////
banker(R, A, C, reqestSequence);
return 0;
}
3、申请资源会出现以下结果:
(1)申请成功
(2)申请失败,因为同意申请会导致系统进入不安全状态
(3)申请失败,其它原因。比如:同意申请将导致该进程获得的资源量大于它声称的最大资源量,或者系统可用资源不足以满足申请,或者两者兼有之。
第(1)种结果,输出0
第(2)种结果,输出1
第(3)种结果,输出2
4、同一个状态,可以做无数次申请测试,每次都是基于该状态申请,而不是基于前一次的结果状态申请。以“样例输入”来说,6次资源申请都是在初始状态下申请的,可以理解为对初始状态分别做了6次申请测试,并不是第2次在第1次申请的结果上进行。
四、输入输出格式描述
以“样例输入、样例输出”为示范,输入输出格式描述如表1所示。
表1. 输入输出格式描述
输入
4 5
5 2 6 5 3
1 1 2 1 3
2 2 2 1 0
2 1 3 1 0
1 1 2 2 1
1 0 2 1 1
2 0 1 1 0
1 1 0 1 0
1 1 1 1 0
4
0 0 0 0 0 2
1 1 0 0 0 0
2 0 0 3 0 0
3 0 0 1 1 1
输出
1
2
2
0
0,2,1
样例输入
5 3 10 5 7 7 5 3 3 2 2 9 0 2 2 2 2 4 3 3 0 1 0 2 0 0 3 0 2 2 1 1 0 0 2 6 1 1 0 2 1 1 2 2 4 3 3 0 0 3 5 1 2 5 0 0 2 5 1 0
样例输出
0 1,3,0,2,4 0 3,0,2,4 1 2 2 2
代码如下
#include <iostream>
#include <vector>
using namespace std;
void banker(vector<int> &R, vector<vector<int> > &A, vector<vector<int> > &C, vector<vector<int> > &reqestSequence);
int main()
{
int n, m; // 系统中有 n 个进程、m 种不同类型的资源
int N; // 进程请求资源的次数
int i, j;
cin >> n; // 输入进程数量
cin >> m; // 输入资源类型数
vector<int> R(m); // R 向量表示系统中每种资源的的总量
for (i = 0; i < m; i++) // 对 m 种资源,输入每种资源的总量,保存到向量 R 中
{
cin >> R[i];
}
vector<vector<int> > C(n, vector<int>(m)); // C 为 Claim 矩阵,即最大需求矩阵,教材上称 Max 矩阵
for (i = 0; i < n; i++) // 输入 C 矩阵
{
for (j = 0; j < m; j++)
{
cin >> C[i][j];
}
}
vector<vector<int> > A(n, vector<int>(m)); // A 为 Allocation 矩阵,即分配矩阵
for (i = 0; i < n; i++) // 输入 A 矩阵
{
for (j = 0; j < m; j++)
{
cin >> A[i][j];
}
}
////////////////////////////////////////////////////////////////////////////////
// 欲针对当前状态做 N 次资源请求测试,故这里一次性输入 N 次资源请求,每次资源请
// 求需要输入 m+1 个整数:第 0 个整数表示申请资源的进程号(取值范围:0 至 n-1);
// 第 1 至 m 个整数分别表示当前状态下,该进程对 m 种资源的申请数量。
cin >> N; // 输入进程请求资源的次数
vector<vector<int> > reqestSequence(N, vector<int>(m + 1));
for (i = 0; i < N; i++)
{
for (j = 0; j <= m; j++)
{
cin >> reqestSequence[i][j];
}
}
//
////////////////////////////////////////////////////////////////////////////////
banker(R, A, C, reqestSequence);
system("pause");
return 0;
}
//R 向量表示系统中每种资源的的总量 C 为 Claim 矩阵,即最大需求矩阵,教材上称 Max 矩阵 A为 Allocation 矩阵,即分配矩阵
void banker(vector<int> &R, vector<vector<int> > &A, vector<vector<int> > &C, vector<vector<int> > &reqestSequence)
{
int i, j, k;
int m = R.size(); //m种不同类型资源
int n = A.size(); //系统中有n个进程
vector<vector<int> > need(n, vector<int>(m)); //进程还需要的各类资源数 即课本上的need矩阵
vector<vector<int> > need_temp(n, vector<int>(m)); //进程还需要的各类资源数 need的矩阵的备份
vector<int> available(m); //剩余资源数
vector<int> work(m); //剩余资源数 是available矩阵的备份
vector<vector<int> > A_temp(n, vector<int>(m)); //已获得的资源数矩阵 A矩阵的备份 A矩阵即为课本allocation矩阵
available = R;
for (j = 0; j < m; j++) //按列遍历 方便计算剩余资源数
{
for (i = 0; i <n; i++)
{
need[i][j] = C[i][j] - A[i][j];
available[j] -= A[i][j];
}
}
for (i = 0; i < reqestSequence.size(); i++) //遍历申请资源的 进程
{
work = available; //备份available矩阵
need_temp = need; //备份need矩阵
A_temp = A; //备份allocation矩阵
int w = reqestSequence[i][0]; //获取 当前申请资源的进程号
int judge = 0; //若 申请资源后 拥有的资源数 大于宣称最大资源数则judge置1;如果系统剩余资源数不能满足申请则 judge置2, 否则judge=0
for (j = 0; j < m; j++)
{
if (reqestSequence[i][j + 1]>need[w][j]) //本次请求导致所占有资源数大于宣称的最大资源数
{
cout <<2<<endl;
judge = 1;
break;
}
}
if (judge == 0)
{
for (j = 0; j < m; j++)
{
if (reqestSequence[i][j + 1]>available[j]) //系统资源不足,无法满足需求
{
cout <<2<<endl;
judge = 2;
break;
}
}
}
if (judge == 0)
{
int temp = 1; //标记位 当前申请资源的进程是否可以直接执行 1可以直接执行;0 表示需要等待
for (j = 0; j < m; j++) //假设先给该进程分配资源
{
work[j] -= reqestSequence[i][j + 1]; //更新系统剩余资源
A_temp[w][j] += reqestSequence[i][j + 1]; //更新已分配资源矩阵
need_temp[w][j] -= reqestSequence[i][j + 1];//更新need矩阵
if (need_temp[w][j]>0)
temp = 0; //该进程是否需要等待,若need[][]>0 表示 分配给的该进程的资源还未达到 该进程宣称的最大资源 就需要等待
} //need[i][j]=C[i][j]-A[i][j] C[][]表示宣称最大资源矩阵,即书上的Max矩阵,A[][]表示已分配资源矩阵,即书上的allocation矩阵
vector<bool> finish(n); //标记进程是否进入安全序列 flase表示还没有进入安全序列 true 表示该进程已经入安全序列
int ans[100];
for (j = 0; j < n; j++) //初始状态时,所有进程都没有进入安全序列
{
finish[j] = false;
}
if (temp == 1) //如果该进程可以直接执行,则释放分配给该进程的资源 ,该进程也无需进入安全序列(题目要求)
{
for (j = 0; j < m; j++)
{
work[j] += A_temp[w][j];
finish[w] = true;
}
}
int flag;
int time = 0;
int t = 0;
while (time<n) //寻找安全序列
{
for (k = 0; k < n; k++) //遍历进程
{
flag = 1;
for (j = 0; j < m; j++) //flag 为1表示 need[i][j]<=available[j] 否则置0
{
if (need_temp[k][j]>work[j])
{
flag = 0;
break;
}
}
if (finish[k] == false && flag==1)
{
for (j = 0; j < m; j++)
{
work[j] += A_temp[k][j];
}
finish[k] = true;
ans[t++] =k;
break;
}
}
time++;
}
for (k = 0; k < n; k++)
{
if (finish[k] == false)
break;
}
if (k != n) //如果没有找到一个安全序列则该资源申请不安全
cout <<1<<endl;
else
{
cout <<0<< endl;
for (j = 0; j < t; j++)
{
if (j != 0)
cout << ',' << ans[j];
else
cout << ans[j];
}
cout << endl;
}
}
}
}