实验二 银行家算法
一、实验目的
死锁会引起计算机工作僵死,因此操作系统中必须防止。本实验的目的在于让
学生独立的使用高级语言编写和调试一个系统动态分配资源的简单模拟程序,了解
死锁产生的条件和原因,并采用银行家算法有效地防止死锁的发生,以加深对课堂
上所讲授的知识的理解。
二、实验要求
设计有 n 个进程共享 m 个系统资源的系统,进程可动态的申请和释放资源,系
统按各进程的申请动态的分配资源。
系统能显示各个进程申请和释放资源,以及系统动态分配资源的过程,便于用
户观察和分析;
- 数据结构
- 可利用资源向量 Available ,它是一个含有 m 个元素的数组,其中的每一个元素代表一类可利用的资源的数目,其初始值是系统中所配置的该类全部可用资源数目。其数值随该类资源的分配和回收而动态地改变。如果 Available(j)=k,表示系统中现有 Rj 类资源 k 个。
- 最大需求矩阵 Max,这是一个 n×m 的矩阵,它定义了系统中 n 个进程中的每一个进程对m类资源的最大需求。如果 Max(i,j)=k,表示进程 i 需要 Rj 类资源的最大数目为 k。
- 分配矩阵 Allocation,这是一个 n×m 的矩阵,它定义了系统中的每类资源当前分配到每一个进程的资源数。如果 Allocation(i,j)=k,表示进程 i 当前已经分到 Rj 类资源的数目为 k。Allocation i表示进程 i 的分配向量,由矩阵 Allocation的第 i 行构成。
- 需求矩阵 Need,这是一个 n×m 的矩阵,用以表示每个进程还需要的各类资源的数目。如果 Need(i,j)=k,表示进程 i 还需要 Rj 类资源 k 个,才能完成其任务。Need i表示进程 i 的需求向量,由矩阵 Need 的第 i 行构成。
上述三个矩阵间存在关系:Need(i,j)=Max(i,j)-Allocation(i,j);
四、实验方案
五、实验代码
//头文件
#pragma once
#include<vector>
class process
{
typedef unsigned process_u;
std::vector<process_u> Available;
std::vector<std::vector<process_u>> Max;
std::vector<std::vector<process_u>> Allocation;
std::vector<std::vector<process_u>> Need;
bool is_safe()const;
void print()const;
public:
process();
~process()=default;
void banker();
};
//源文件
#include "process.h"
#include<fstream>
#include<iostream>
using namespace std;
process::process()
{
ifstream p_write("information.txt");
if (!p_write.is_open())
{
cerr << "error process" << endl;
return;
}
process_u n, m;
p_write >> n >> m;//表示n个进程,m种资源
//当前可获得资源
Available = vector<process_u>(m);
//进程完成最大资源
Max = vector<vector<process_u>>(n, vector<process_u>(m));
//已分配资源
Allocation = vector<vector<process_u>>(n, vector<process_u>(m));
//仍需要资源
Need = vector<vector<process_u>>(n, vector<process_u>(m));
//Available初始化
for (process_u i = 0; i < m; i++)
p_write >> Available[i];
//Max初始化
for (process_u i = 0; i < n; i++)
for (process_u j = 0; j < m; j++)
p_write >> Max[i][j];
//Allocation初始化
for (process_u i = 0; i < n; i++)
for (process_u j = 0; j < m; j++)
{
p_write >> Allocation[i][j];
if (Allocation[i][j] > Max[i][j])
{
cerr << "The allcation of process i is too big" << endl;
return;
}
}
p_write.close();
//Need=Max-Allocation
for (process_u i = 0; i < n; i++)
{
for (process_u j = 0; j < m; j++)
{
Need[i][j] = Max[i][j] - Allocation[i][j];
}
}
}
void process::banker()//回溯算法
{
process_u sum = 0;
//如果T0时不够,直接失败
if (!is_safe())
{
cerr << "The initial condition is bad" << endl;
return;
}
cout << "当前状态:" << endl;
print();
do
{
//哪一个进程
cout << "请输入进程号,那种资源,请求多少:" << endl;
vector<process_u> request(Max[0].size());
process_u i;
cin >> i;
bool temp = true;
for (process_u m = 0; m < request.size(); m++)
{
cin >> request[m];
temp = temp && (request[m] <= Need[i][m] && request[m] <= Available[m]);
}
if (temp)
{
for (process_u j = 0; j < request.size(); j++)
{
Available[j] = Available[j] - request[j];
Allocation[i][j] = Allocation[i][j] + request[j];
Need[i][j] = Need[i][j] - request[j];
}
}
else
{
cout << "请求高于需要或者高于当前可用资源" << endl;
continue;
}
if (!is_safe())
{
for (process_u j = 0; j < request.size(); j++)
{
Available[j] = Available[j] + request[j];
Allocation[i][j] = Allocation[i][j] - request[j];
Need[i][j] = Need[i][j] + request[j];
}
cout << "请求不可接受" << endl;
}
else
{
cout << "请求可接受" << endl;
print();
}
sum = 0;//表示都已结束
for (process_u i = 0; i < Need.size(); i++)
{
for (process_u j = 0; j < Need[0].size(); j++)
sum += Need[i][j];
}
} while (sum);
}
bool process::is_safe()const
{
vector<process_u> Work = Available;
vector<bool> Finish = vector<bool>(Max.size(), false);
bool is_changed;
do
{
is_changed = false;//表示当前状态是否改变过
//安全的情况只有当前状况能够改变,或者Finish全为true
for (process_u i = 0; i < Max.size(); i++)
{
bool mark = true;//表示当前进程i能否完成
if (!Finish[i])//完成的不用再执行
{
for (process_u j = 0; j < Max[0].size(); j++)
{
if (Work[j] < Need[i][j])//只要有一种资源不够则不能完成
{
mark = false;
break;
}
}
if (mark)//如果足够就分配直至完成收回
{
Finish[i] = true;
for (process_u j = 0; j < Max[0].size(); j++)
Work[j] += Allocation[i][j];
is_changed = true;
}
}
}
if (!is_changed)//如果没有改变
{
bool temp = true;
for (process_u i = 0; i < Max.size(); i++)
temp = temp && Finish[i];
if (!temp)//只要temp有一个为false就不安全
return false;
}
} while (is_changed);//跳出循环只能是is_changed=false或者是Finish全为true
return true;
}
void process::print()const
{
cout << "Max:" << endl;
for (process_u i = 0; i < Max.size(); i++)
{
cout << "thread_id" << i<<":";
for (process_u j = 0; j < Max[0].size(); j++)
cout << Max[i][j] << " ";
cout << endl;
}
cout << "Allocation:" << endl;
for (process_u i = 0; i < Allocation.size(); i++)
{
cout << "thread_id" << i << ":";
for (process_u j = 0; j < Allocation[0].size(); j++)
cout << Allocation[i][j] << " ";
cout << endl;
}
cout << "Need:" << endl;
for (process_u i = 0; i < Need.size(); i++)
{
cout << "thread_id" << i << ":";
for (process_u j = 0; j < Need[0].size(); j++)
cout << Need[i][j] << " ";
cout << endl;
}
cout << "Available:" << endl;
for (process_u i = 0; i < Available.size(); i++)
cout << Available[i] << " ";
cout << endl;
}
六、预习中的问题及对应思考
- 判断是否安全,就是寻找能否有一个安全序列,寻找每一步就是要看当前状态能否改变。如果能够改变,则继续下一步改变,如果没有改变,就看是否全部完成。如果全部完成,则安全,否则不安全。
- 银行家算法,类似回溯算法,先分配,查看是否安全。如果安全,继续下一次分配,如果不安全,退回分配。