操作系统实验二:银行家算法
一、实验目的
- 了解死锁避免的原理。
- 研究银行家算法的实现方法。
二、实验要求及内容
- 编程实现银行家算法,加深了解有关资源申请、避免死锁等概念,并体会和了解死锁的避免死锁的具体实施方案。
- 列出调试通过程序的清单,并附上文档说明。
- 总结上机调试过程中遇到的问题和解决方法及感想。
三、实验代码
// 银行家算法.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include<vector>
#include<algorithm>
#include <iomanip>
using namespace std;
int num_Process = 0;
int num_Source = 0;
vector<int>TotalSource;
vector<int>Available ;
vector<int>Request;
vector<char> nameSource;
vector<int>SucceesName;
vector<int> work;
vector<int> workallocation;
class BankObject
{
private:
char name;
vector<int> max;
vector<int> allocation;
vector<int> need;
bool finish;
public:
BankObject(char pname,vector<int>pmax, vector<int>pallocation,vector<int>pneed) :
name(pname),max(pmax), allocation (pallocation),need(pneed)
{
finish = 0;
}
operator vector<int>() const
{
return need;
}
vector<int>& Max()
{
return max;
}
const vector<int>& Max()const
{
return max;
}
char& Name()
{
return name;
}
const char& Name()const
{
return name;
}
vector<int>& Allocation()
{
return allocation;
}
const vector<int>& Allocation()const
{
return allocation;
}
vector<int>& Need()
{
return need;
}
const vector<int>& Need()const
{
return need;
}
bool & Finish()
{
return finish;
}
const bool & Finish()const
{
return finish;
}
};
class Manage
{
private:
vector<BankObject> ProList;
public:
//初始化各个进程的Max,Allocation,Need向量
void Add(BankObject process)
{
ProList.push_back(process);
}
void SetWorkAvailable()
{
for (int i = 0; i < num_Source; i++)
{
for (int j = 0; j < num_Process; j++)
{
Available[i] = Available[i] - ProList[j].Allocation()[i];
}
}
work = Available;
}
void CalTotolSource()
{
TotalSource = Available;
for (int i = 0; i < num_Source; i++)
{
for (int j = 0; j < num_Process; j++)
{
TotalSource.push_back( TotalSource[i] + ProList[j].Allocation()[i]);
}
}
}
void CalMax()
{
for (int i = 0; i < num_Process; i++)
{
for (int j = 0; j < num_Source; j++)
{
ProList[i].Max()[j] = ProList[i].Allocation()[j] + ProList[i].Need()[j];
}
}
}
void CalNeed()
{
for (int i = 0; i < num_Process; i++)
{
for (int j = 0; j < num_Source; j++)
{
ProList[i].Need()[j] = ProList[i].Max()[j] - ProList[i].Allocation()[j];
}
}
}
void CalAllocation()
{
for (int i = 0; i < num_Process; i++)
{
for (int j = 0; j < num_Source; j++)
{
ProList[i].Allocation()[j] = ProList[i].Max()[j] - ProList[i].Need()[j];
}
}
}
bool Compare(BankObject obj1, vector<int>work)
{
bool success = true;
for (int i = 0; i < num_Source; i++)
{
if (obj1.Need()[i] > work[i])//安全性算法Step1:比较不成功
{
success = false;
}
}
return success;
}
bool SafeCheak()
{
cout << "资源 " << setw(2) << "Work" << setw(8) << "Need" << setw(13) << "Allocation" << setw(17) << "Work+Allocation" << setw(8) << "Finish" << endl;
cout << "进程" << setw(4);
for (int j = 0; j < 4; j++)
{
cout << setw(3);
if (j == 2)
{
cout << setw(4);
}
if (j == 3)
{
cout << setw(8);
}
for (int i = 0; i < num_Source; i++)
{
cout << nameSource[i] << " ";
}
}
cout << endl;
bool success = 0;
int tag = 0;
//Step1:设置两个工作向量(已完成)
//Step2:从进程集合中找满足条件的进程
for (int k = 0, count = 0; k < num_Process; k++)
{
for (int i = 0; i < num_Process; i++)
{
if (ProList[i].Finish() == 0 && Compare(ProList[i], work))
{
//打印通过安全检查进程的Work,Need,Allocation
SucceesName.push_back(i);
cout << "P" << i << setw(4) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << work[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
cout << setw(2) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << ProList[i].Need()[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
ProList[i].Finish() = 1;
//打印Work+Allocation矩阵,
cout << setw(3) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << ProList[i].Allocation()[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
for (int j = 0; j < num_Source; j++)
{
work[j] = work[j] + ProList[i].Allocation()[j];
}
cout << setw(7) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << work[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
cout << setw(10) << "|" << ProList[i].Finish() << "|" << endl;
count++;//找到一个安全序列
if (count == num_Process)//找到所有的安全序列
{
success = 1;
//打印安全序列
cout << "------------***^*^***-------------" << endl;
cout << "系统处于安全状态,可以找到一个安全序列{";
for (int j = 0; j < num_Process; j++)
{
cout << "P";
cout << SucceesName[j] << ",";
}
cout << "}" << endl;
cout << "------------***^*^***-------------" << endl;
goto end;
}
}
}
}
if (success == 0)//没有找到安全序列
{
cout << "------------***^*^***-------------" << endl;
cout << "该系统未处于安全状态!" << endl;
cout << "------------***^*^***-------------" << endl;
}
end:
for (int i = 0; i < num_Process; i++)
{
ProList[i].Finish() = 0;
}
return success;
}
//processi是要请求的进程序列
void BankAlgorithm(int processi)
{
//Step1:
bool success = 1;
for (int j = 0; j < num_Source; j++)
{
if (Request[j] > ProList[processi].Need()[j])
{
success = 0;
cout << "该进程所申请的资源数量已经超过他所宣布的最大值!" << endl;
}
}
//其余步骤都是在step1执行成功的条件下执行的
//Step2:
if (success)
{
for (int j = 0; j < num_Source; j++)
{
if (Request[j] > Available[j])
{
success = 0;
cout << "系统尚无足够资源!P"<<processi<<"进程须等待!" << endl;
}
}
}
//Step3:系统试分配
if (success)
{
for (int j = 0; j < num_Source; j++)
{
Available[j] = Available[j] - Request[j];
ProList[processi].Allocation()[j] = ProList[processi].Allocation()[j] + Request[j];
ProList[processi].Need()[j] = ProList[processi].Need()[j] - Request[j];
}
work = Available;
success = SafeCheak();
if (success == 0)//安全性检查未通过
{
//回收刚才试分配的资源
for (int j = 0; j < num_Source; j++)
{
Available[j] = Available[j] + Request[j];
ProList[processi].Allocation()[j] = ProList[processi].Allocation()[j] - Request[j];
ProList[processi].Need()[j] = ProList[processi].Need()[j] + Request[j];
}
work = Available;
}
}
}
void Print_T0()
{
cout << "资源 " << setw(3) << "Max" << setw(13) << "Allocation" << setw(6) << "Need" << setw(11) << "Available" << endl;
cout << "进程" << setw(4);
for (int j = 0; j < 4; j++)
{
cout << setw(3);
if (j == 2)
{
cout << setw(4);
}
if (j == 3)
{
cout << setw(5);
}
for (int i = 0; i < num_Source; i++)
{
cout << nameSource[i] << " ";
}
}
cout << endl;
for (int i = 0; i < num_Process; i++)
{
cout << "P" << i << setw(4) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << ProList[i].Max()[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
cout << setw(2) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << ProList[i].Allocation()[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
cout << setw(3) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << ProList[i].Need()[j];
if (j + 1 == num_Source)
{
cout << "|";
break;
}
cout << " ";
}
if (0 == i)
{
cout << setw(3) << "|";
for (int j = 0; j < num_Source; j++)
{
cout << Available[j] << setw(2);
}
cout << "|";
}
cout << endl;
}
}
void Menu()
{
cout << "**********^^^*^^^********" << endl;
cout << "1.显示当前资源情况" << endl;
cout << "2.安全性检查" << endl;
cout << "3.请求资源" << endl;
cout << "4.退出本系统" << endl;
cout << "**********^^^*^^^********" << endl;
}
void InitMenu()
{
cout << "1.输入Max,allocation,totalsource" << endl;
cout << "2.输入allocation,need,available" << endl;
cout << "3.输入Max,Need,available" << endl;
}
};
void CharName()
{
for (int i = 0; i < num_Source; i++)
{
nameSource.push_back(i + 65);
}
}
int main()
{
Manage process;
bool success;
int choose = 0;
int processi = 0;
char end = 'y';
vector<int> num_Max;
vector<int> num_Allocation;
vector<int> num_Need;
int requestsourcenum = 0;
cout<<"现在开始进行初始化:"<<endl;
cout << "请输入进程的数量:";
cin >> num_Process;
cout << "请输入资源的数量:";
cin >> num_Source;
CharName();
int valueAvailable = 0;
int valueMax = 0, valueAllocation = 0, valueNeed = 0;
int init = 0;
process.InitMenu();
way:
cout << "请选择初始化方式:";
cin >> init;
if (1 == init)
{
for (int i = 0; i < num_Source; i++)
{
cout << "请输入资源" << nameSource[i] << "的总量:";
cin >> valueAvailable;
TotalSource.push_back(valueAvailable);
}
for (int i = 0; i < num_Process; i++)
{
cout << "请输入进程P" << i << "的Max:";
for (int j = 0; j < num_Source; j++)
{
cin >> valueMax;
num_Max.push_back(valueMax);
}
cout << "请输入进程P" << i << "的Allocation:";
for (int j = 0; j < num_Source; j++)
{
cin >> valueAllocation;
num_Allocation.push_back(valueAllocation);
num_Need.push_back(0);
}
BankObject obj1(i, num_Max, num_Allocation,num_Need);
process.Add(obj1);
num_Max.clear();
num_Allocation.clear();
num_Need.clear();
}
Available = TotalSource;
process.CalNeed();
process.SetWorkAvailable();
}
else if(2==init)
{
for (int i = 0; i < num_Process; i++)
{
cout << "请输入进程P" << i << "的Allocation:";
for (int j = 0; j < num_Source; j++)
{
cin >> valueAllocation;
num_Allocation.push_back(valueAllocation);
}
cout << "请输入进程P" << i << "的Need:";
for (int j = 0; j < num_Source; j++)
{
cin >> valueNeed;
num_Need.push_back(valueNeed);
num_Max.push_back(0);
}
BankObject obj1(i, num_Max, num_Allocation,num_Need);
process.Add(obj1);
num_Max.clear();
num_Allocation.clear();
num_Need.clear();
}
for (int i = 0; i < num_Source; i++)
{
cout << "请输入资源" << nameSource[i] << "的available:";
cin >> valueAvailable;
Available.push_back(valueAvailable);
}
//计算各资源的总数
process.CalTotolSource();
process.CalMax();
work = Available;
}
else if (3 == init)
{
for (int i = 0; i < num_Process; i++)
{
cout << "请输入进程P" << i << "的Max:";
for (int j = 0; j < num_Source; j++)
{
cin >> valueMax;
num_Max.push_back(valueMax);
}
cout << "请输入进程P" << i << "的Need:";
for (int j = 0; j < num_Source; j++)
{
cin >> valueNeed;
num_Need.push_back(valueNeed);
num_Allocation.push_back(0);
}
BankObject obj1(i, num_Max, num_Allocation, num_Need);
process.Add(obj1);
num_Max.clear();
num_Allocation.clear();
num_Need.clear();
}
for (int i = 0; i < num_Source; i++)
{
cout << "请输入资源" << nameSource[i] << "的available:";
cin >> valueAvailable;
Available.push_back(valueAvailable);
}
//计算各资源的总数
process.CalTotolSource();
process.CalAllocation();
work = Available;
}
else
{
cout << "请重新输入初始化方式!" << endl;
goto way;
}
while (1)
{
process.Menu();
cout << "请输入你的选择:";
cin >> choose;
if (choose < 0 || choose>4)
{
cout << "请重新输入你的选择!" << endl;
}
switch (choose)
{
case 1:
process.Print_T0();
break;
case 2:
process.SafeCheak();
break;
case 3:
cout << "进程列表:" << endl;
for (int i = 0; i < num_Process; i++)
{
cout << "P" << i << "-->" << i << endl;
}
process:
cout << "请输入要申请资源的进程:";
cin >> processi;
if (processi<0 || processi>num_Process)
{
cout << "对不起,请重新输入进程!!!" << endl;
goto process;
}
cout << "请输入要申请的各种资源数量:";
for (int i = 0; i < num_Source; i++)
{
cin >> requestsourcenum;
Request.push_back(requestsourcenum);
}
process.BankAlgorithm(processi);
Request.clear();
break;
case 4:
return 0;
break;
}
}
}
四、实验结果截图
1.初始化
2、 显示当前资源情况:
3、 安全性检查:
4、 P1请求资源
5、 P4请求资源:
6、 P3请求资源:
五、实验总结
通过此次实验,我对银行家算法的理解更加深入,了解死锁避免的基本思想是动态地检测资源分配状态,以确保循环等待条件不成立,从而确保系统处于安全状态。认识到所谓安全状态是指:如果系统能按某个顺序为每个进程分配资源(不超过其最大值),那么系统状态是安全的,换句话说就是,如果存在一个安全序列,那么系统处于安全状态。
在这次实验过程中我遇到了代码运行不出来的情况,为此我十分焦虑,不过在不断查阅资料的和翻看书本的情况下我用c++实现了银行家算法;这次实验让我了解和如何避免死锁,系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源;如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。总之,我学到了很多。