银行家算法模拟
核心思想:
先对用户提出的请求进行合法性检查,即检查请求的是否不大于需要的,是否不大于可利用的。
若请求合法,则进行试分配。
最后对试分配后的状态调用安全性检查算法进行安全性检查。
若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
const int maxn=50; //假设最多有50类资源
const int maxm=30; //假设最多有30个进程
//银行家算法的数据结构
string resourceName[maxn]; //用来保存资源名称
string proName[maxm]; //用来保存进程名称
int Available[maxn]; //可以用的资源Available[i] 表示第i种资源的可利用数量
int Max[maxm][maxn]; //最大需求矩阵 Max[i][j] 第j个进程对第i中资源的最大需求量
int Allocation[maxm][maxn]; //每个进程对各类资源当前的占有量, Allocation[j][i]表示第j个项目已获取的第i类资源
int Need[maxm][maxn]; //表示每个进程对各类资源尚需要的数目Need = Max-Allocation
int Request[maxn]; //表示某个进程对当前各类资源的申请数量
//安全性子算法
int Work[maxn]; //表示系统可提供给进程继续运行所需要的各类资源的数目,初始Work=Available
bool Finish[maxn];//表示是否有足够的资源分配给进程使之运行完成,Finish[i]=true 表示当前系统的i类资源是可以满足当前进程的运行的
//最开始的时候Finish[i]=false,当有足够资源分配给进程时,Finish[i]=true
string Security[maxn]; //存放安全序列
//全局变量
int proNum; //全局变量的数量
int resourceNum; //一共有多少类资源
//所有数组,下标从1开始,第一个进程,第一种资源
/*
核心思想:
先对用户提出的请求进行合法性检查,即检查请求的是否不大于需要的,是否不大于可利用的。
若请求合法,则进行试分配。
最后对试分配后的状态调用安全性检查算法进行安全性检查。
若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。
*/
void initResources()
{
for(int i=1;i<=resourceNum;i++)
{
Available[i] = rand()%10+1; //最开始每类资源的数目在1~10之间,随机生成
resourceName[i] = "R"+to_string(i);
}
}
void initPro()
{
//创建进程所需要的信息
for(int i=1;i<=proNum;i++)
{
proName[i] = "P"+to_string(i); //第i个进程
for(int j=1;j<=resourceNum;j++) //有resourceNum列
{
Max[i][j] = rand()%10; //0-10对该类资源的最大需求量
Allocation[i][j] = rand()%8; //已拥有的该类资源0-8
if(Max[i][j]<Allocation[i][j])
swap(Max[i][j],Allocation[i][j]);
Need[i][j] = Max[i][j] - Allocation[i][j]; //还需要的该类资源
}
}
}
//有关安全性算法的数组初始化
void initSafe()
{
for(int i=1;i<=resourceNum;i++)
{
Work[i] = Available[i];
}
memset(Finish, false, sizeof(Finish));
}
void test(int i) //尝试将资源分配给第i个进程
{
for(int j=1;j<=resourceNum;j++)
{
Available[j] = Available[j]-Request[j];
Allocation[i][j] = Allocation[i][j]+Request[j];
Need[i][j] = Need[i][j]-Request[j];
}
}
void reTest(int i)//撤销在第i个进程上所做的尝试
{
for (int j = 1; j <= resourceNum; j++)
{
Available[j] = Available[j]+Request[j];
Allocation[i][j] = Allocation[i][j]-Request[j];
Need[i][j] = Need[i][j]+Request[j];
}
}
//安全性算法;检测当前系统是否处于安全状态
bool safe()
{
int i,j,k=1,m,apply;
initSafe(); //对Work和Finish的初始化
//求安全序列
for(i=1;i<=proNum;i++) //i代表的是进程, j代表的是资源
{
apply=0;
for(j=1;j<=resourceNum;j++) //遍历每一类资源
{
if(Finish[i]==false && Need[i][j]<=Work[j])
{
apply++;
}
}
//直到每类资源尚需数都小于系统可利用资源数才可分配
if(apply==resourceNum) //可以分配啦
{
for(m=1;m<=resourceNum;m++) //遍历每一类资源,回收资源
Work[m]=Work[m]+Allocation[i][m];//更改当前可分配资源(i进程已经拥有的m类资源的数量)
Finish[i]=true; //第i个进程完成
Security[k++]=proName[i];
i=0; //保证每次查询均从第一个进程开始
}
}
for(i=1;i<=proNum;i++)
{
if(Finish[i]==false) //该调度下,无法执行完所有的进程
{
printf("当前系统不安全!\n");//不成功系统不安全
return false;
}
}
printf("系统是安全的!\n");//如果安全,输出成功
printf("存在一个安全序列:");
for(i=1;i<=proNum;i++){//输出运行进程数组
cout << Security[i];
if(i<proNum)
printf("->");
}
printf("\n");
printf("资源分配完毕!");
return true;
}
//展示调度情况的算法
void display()
{
int i,j;
printf("*************************************************************\n");
printf("系统目前可用的资源[Available]:\n");
printf("资源名称 ");
for(i=1;i<=resourceNum;i++) //输出资源名称
cout << resourceName[i] << " ";
printf("\n");
printf("资源剩余量");
for(i=1;i<=resourceNum;i++) //输出资源剩余量
printf("%4d ",Available[i]);
// cout << Available[i] << " ";
printf("\n");
printf("系统当前的资源分配情况如下:\n");
printf(" Max Allocation Need\n");
printf("进程名 ");
//输出与进程名同行的资源名,Max、Allocation、Need下分别对应
for(j=0;j<3;j++){
for(i=1;i<=resourceNum;i++)
cout << resourceName[i] << " ";
printf(" ");
}
printf("\n");
//输出每个进程的Max、Allocation、Need
for(i=1;i<=proNum;i++){
cout << proName[i] << " ";
for(j=1; j<=resourceNum;j++)
printf(" %d ",Max[i][j]);
printf(" ");
for(j=1;j<=resourceNum;j++)
printf(" %d ",Allocation[i][j]);
printf(" ");
for(j=1;j<=resourceNum;j++)
printf(" %d ",Need[i][j]);
printf("\n");
}
}
void bank()
{
bool flag = true;//标志变量,判断能否进入银行家算法的下一步
int i,j;
printf("请输入请求分配资源的进程号:");
cin >> i;//输入须申请资源的进程号
printf("请输入进程P%d要申请的资源个数:\n",i);
for(j=1;j<=resourceNum;j++)
{
cout << resourceName[j] << ":";
cin >> Request[j]; //需要申请的资源数
}
//判断银行家算法的前两条件是否成立
for (j=1; j<=resourceNum;j++)
{
if(Request[j]>Need[i][j])//判断申请是否大于需求,若大于则出错
{
printf("进程P%d申请的资源大于它需要的资源",i);
printf("分配不合理,不予分配!\n");
flag = false;
break;
}
else
{
if(Request[j]>Available[j])//判断申请是否大于当前可分配资源,若大于则出错
{
printf("进程%d申请的资源大于系统现在可利用的资源",i);
printf("\n");
printf("系统尚无足够资源,不予分配!\n");
flag = false;
break;
}
}
}
//前两个条件成立,试分配资源,寻找安全序列
if(flag) {
test(i); //根据进程需求量,试分配资源
display(); //根据进程需求量,显示试分配后的资源量
if(!safe()) //寻找安全序列,如果不安全要进行资源的撤销
{
reTest(i);
cout << "进行资源的回退!" << endl;
display();
}
}
}
int main()
{
char isContinue;
cout << "请输入资源的种类数目:";
cin >> resourceNum;
cout << "请输入进程的数目:";
cin >> proNum;
//1-初始化资源信息(构造Available,创建随机数据)
initResources();
cout << "初始化资源信息完毕!" << endl;
//2-初始化进程相关数组
initPro();
cout << "初始化进程相关数据完毕!" << endl;
//3-展示数据
display();
//4-判断当前时刻系统是否处于安全状态
if(!safe()) exit(0); //如果不是安全状态直接退出
//3-开始银行家算法分配资源
cout << "是否进行银行家算法进行资源分配(y/n)?" ;
cin >> isContinue;
while(isContinue=='y')
{
bank();
cout << "是否继续进行银行家算法进行资源分配(y/n)?" ;
cin >> isContinue;
}
return 0;
}