一、实验目的
1、进一步理解利用银行家算法避免死锁的问题;
2、在了解和掌握银行家算法的基础上,编制银行家算法通用程序,将调试结果显示在计算机屏 幕上,再检测和笔算的一致性。
3、理解和掌握安全序列、安全性算法。
二、实验要求
1、了解和理解死锁;
2、理解利用银行家算法避免死锁的原理;
3、会使用某种编程语言。
三、实验原理
3.1、安全状态
指系统能按照某种顺序如(称为序列为安全序列),为每个进程分 配所需的资源,直至最大需求,使得每个进程都能顺利完成。
3.2、银行家算法
假设在进程并发执行时进程 i 提出请求 j 类资源 k 个后,表示为 Requesti[j]=k。系统按下述步骤进行安全检查:
1)如果 Requesti≤Needi 则继续以下检查,否则显示需求申请超出最大需求值的错误。
2)如果 Requesti≤Available 则继续以下检查,否则显示系统无足够资源,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.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 都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。
四、结果展示
正如上课时的PPT所示:
先初始化表格中的Max矩阵、Allocation矩阵、Available矩阵。Need矩阵可由Max与Allocation计算得出。Need=Max-Allocation。
本次实验的测试数据是5个进程,4种资源,根据测试数据,初始化上述表格:
初始化以后的表格如下图所示:
接下来程序会调用安全算法,测试当前状态系统是否安全,测试顺序如下:
Work=Available,依次判断Need是否小于等于Work,如果小于等于,就分配资源,进程运行完成之后,收回分配给进程的所有资源。再次寻找满足Need小于等于Work的进程,重复上述步骤,直至所有进程的Finish=true,或者剩余的所有进程都不满足Need<=Work的条件。
由上图所示,所有进程的Finish=true,所以系统是安全的,测试序列就是安全序列。即:
系统是安全的,因此接下来可以响应部分进程的请求资源申请,假设进程1 request(0,4,2,0),request需满足两个条件:
Request<=available;
Request<=Need.
若同时满足两个条件,就进行预分配:
Available-=Request
Need-=Request
Allocation+=Request
结果如下:
接下来调用安全算法判断当前状态是否安全:
从结果来看,由于所有进程的Finish=true,所以系统安全,同意分配。安全序列为:
此时,如果进程1再一次申请资源,假设进程1 Request(0,1,1,0),那么系统将无法提供进程1需要的资源:
五、实验代码
#include <iostream>
using namespace std;
//全局变量定义
int Available[100]; //系统可用资源数组
int Max[50][100]; //进程最大需求数组
int Allocation[50][100]; //进程已分配资源矩阵
int Need[50][100]; //进程还需资源数组
int Request[50][100]; //M个进程还需要N类资源的资源量
int Finish[50];//安全算法中判断是否可以给某个进程分配资源
int safe_sequence[50];//安全序列
int m, n; //M个进程,N类资源
//安全性算法
int Safe()
{
int i, j, safe_sequence_length = 0;
int Work[100]; //可利用资源数组
int Work1[50][100],Work_Allocation[50][100],Work1_i=0,Work_Allocation_i=0;
//初始化系统可用资源
for (i = 0; i < n; i++) {
Work[i] = Available[i];
}
for (i = 0; i < m; i++) {
Finish[i] = 0;
}
for (i = 0; i < m; i++)
{
if (Finish[i] == 1) {//找一个Finish[i]!=true的进程
continue;
}
else
{
//判断该进程需要的资源是否小于系统可用资源,即找到need<=work的进程
for (j = 0; j < n; j++)
{
if (Need[i][j] > Work[j]) {
break;
}
}
//如果找到这样的进程,即当前进程满足need<=work的要求
if (j == n)
{
Finish[i] = 1;
for (int k = 0; k < n; k++) {
Work1[Work1_i][k] = Work[k];//方便可视化
Work[k] += Allocation[i][k];//收回该进程已经分配的资源
Work_Allocation[Work_Allocation_i][k] = Work[k];//方便可视化
}
Work1_i++;//方便可视化
Work_Allocation_i++;//方便可视化
safe_sequence[safe_sequence_length++] = i;//当前索引i对应的进程已经获得所需资源,运行结束,将进程PCB号加入安全序列中
i = -1;
}
else {//当前进程不满足need<=work的要求,跳过
continue;
}
}
//每判断一个进程是否符合need<=work的要求,都要判断安全序列的长度是否为m,即所有的进程都已经满足要求,所有进程的Finish[i]=true
if (safe_sequence_length == m)
{
//安全算法可视化
cout << "进程\t" << "Work\t\t" << "Need\t\t" << "Alocation\t" << "Work+Alocation " << "Finish"<< endl;
for (i = 0; i < m; i++) {
cout << "P" << safe_sequence[i] << "\t";
for (int k = 0; k < n; k++) {
cout << Work1[i][k] << " ";
}
cout << "\t";
for (int k = 0; k < n; k++) {
cout << Need[safe_sequence[i]][k] << " ";
}
cout << "\t";
for (int k = 0; k < n; k++) {
cout << Allocation[safe_sequence[i]][k] << " ";
}
cout << "\t";
for (int k = 0; k < n; k++) {
cout << Work_Allocation[i][k] << " ";
}
cout << "\t";
if (Finish[i] == 1) {
cout << "true" << "\n\n";
}
else {
cout << "false" << "\n\n";
}
}
cout << "系统是安全的" << '\n';
cout << "系统安全序列是:\n";
for (i = 0; i < safe_sequence_length; i++)
{
cout << safe_sequence[i];
if (i != safe_sequence_length - 1)
cout << "-->";
}
cout << '\n';
return 1;
}
}
cout << "系统不安全" << endl;
return 0;
}
//银行家算法
void banker_algorithm() {
int i, j, process;
cout << "输入进程的数目:\n";
cin >> m;
cout << "输入资源的种类:\n";
cin >> n;
cout << "输入每个进程最多所需的各类资源数,按照" << m << "x" << n << "矩阵输入\n";
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
cin >> Max[i][j];
cout << "输入每个进程已经分配的各类资源数,按照" << m << "x" << n << "矩阵输入\n";
for (i = 0; i < m; i++)
{
for (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 << "请输入各个资源现有的数目:\n";
for (i = 0; i < n; i++) {
cin >> Available[i];//输入各类资源的剩余数量
}
//银行家算法可视化
cout << "进程\t" << "Max\t\t" << "Allocation\t" << "Need\t\t" << "Available" << endl;
for (int i = 0; i < m; i++) {
cout << "P" << i << "\t";
for (int j = 0; j < n; j++) {
cout << Max[i][j]<<" ";
}
cout << "\t";
for (int j = 0; j < n; j++) {
cout << Allocation[i][j]<<" ";
}
cout << "\t";
for (int j = 0; j < n; j++) {
cout << Need[i][j]<<" ";
}
cout << "\t";
if (i == 0) {
for (int j = 0; j < n; j++) {
cout << Available[j]<<" ";
}
}
cout << "\n\n";
}
if (Safe() == 0) {
return;
}
while (1){
cout << "输入要申请的资源的进程号:(第一个进程号为0,第二个进程号为1,依此类推)\n";
cin >> process;
cout << "输入进程所请求的各个资源的数量\n";
for (i = 0; i < n; i++) {
cin >> Request[process][i];
}
//判断是否满足request<=need,request<=available
for (i = 0; i < n; i++){
if (Request[process][i] > Need[process][i])//应满足request<=need,进程申请的各类资源数应该小于其所需要的各类资源数
{
cout << "所请求资源数超过进程的需求量!\n";
return;
}
if (Request[process][i] > Available[i])//应满足request<=available,进程申请的各类资源数应该小于系统剩余各类资源数
{
cout << "所请求资源数超过系统所有的资源数!\n";
return;
}
}
for (i = 0; i < n; i++)
{
Available[i] -= Request[process][i];
Allocation[process][i] += Request[process][i];
Need[process][i] -= Request[process][i];
}
//银行家算法可视化
cout << "进程\t" << "Max\t\t" << "Allocation\t" << "Need\t\t" << "Available" << endl;
for (int i = 0; i < m; i++) {
cout << "P" << i << "\t";
for (int j = 0; j < n; j++) {
cout << Max[i][j] << " ";
}
cout << "\t";
for (int j = 0; j < n; j++) {
cout << Allocation[i][j] << " ";
}
cout << "\t";
for (int j = 0; j < n; j++) {
cout << Need[i][j] << " ";
}
cout << "\t";
if (i == 0) {
for (int j = 0; j < n; j++) {
cout << Available[j] << " ";
}
}
cout << "\n\n";
}
if (Safe()) {
cout << "同意分配请求\n";
}
else
{
cout << "SORRY╮(╯▽╰)╭……你的请求被拒绝…\n";
//恢复预分配之前各进程分配各类资源的资源数
for (i = 0; i < n; i++)
{
Available[i] += Request[process][i];
Allocation[process][i] -= Request[process][i];
Need[process][i] += Request[process][i];
}
}
for (i = 0; i < m; i++) {
Finish[i] = 0;
}
char request_again; //标志位
cout << "是否再次请求分配?是请按Y/y,否请按N/n:";
while (1)
{
cin >> request_again;
if (request_again == 'Y' || request_again == 'y' || request_again == 'N' || request_again == 'n') {
break;
}
else{
cout << "请按要求重新输入:\n";
continue;
}
}
if (request_again == 'Y' || request_again == 'y') {
continue;
}
else {
break;
}
}
}
int main(){
banker_algorithm();
return 0;
}