1、实验目的:
经过对银行家算法的模拟加深对避免死锁的理解,掌握银行家算法和安全性测试算法;
2、实验内容:
系统中有m个同类资源,被n个进程共享,每一个进程对资源的最大需求数分别为S一、S二、…、Sn,且Max(Si)<=m(i=1,2,…,n)。进程能够动态地申请资源和释放资源。编写一个程序,实现银行家算法模拟分配资源以及进行安全性检测。当系统将资源分配给某一进程而不会死锁时,就分配之。不然,推迟分配,并显示适当信息。
3、实验要求:ios
- 将本实验分红两个阶段,第一阶段实现系统安全性检测算法(在系统安全的状况下要求输出安全序列), 第二阶段实现银行家算法。
- 要求用户能自主地输入不一样的向量矩阵。
- 程序能正确输出不一样的运算结果。
- 程序应具有良好的容错能力。
首先是头文件和预处理算法
#include<iostream> #include<fstream> #define pnum 5 #define rnum 3
pnum是processnum也就是进程数量,rnum是resourcenum也就是资源数量,这是一个关于如何合理的分配资源给进程的算法,在操做系统书上有讲解,但愿读者区看看。数组
//定义安全性算法的数据结构 int sign[pnum],//安全序列 work[pnum][rnum],//记录要显示的work,由算法种的work赋值获得,方便打印输出 workAll[pnum][rnum];//work+allocation //定义银行家算法的数据结构 int Available[pnum],//可用资源向量available Max[pnum][rnum],//最大需求向量,每一个进程的最大需求 Allocation[pnum][rnum],//分配矩阵,至关于当前已经分配了 Need[pnum][rnum];//max-allocation,当前还需资源数目向量
根据书上的内容能够做出以下的定义,银行家算法的可用资源,最大等(有批注),安全性算法的work是为了显示,后面的算法中会有体现,work+allocation是根书上保持一致因此这样的一个定义,具体的能够根据书上的表格进行比较,话很少说,老规矩,main函数分析。安全
首先在main函数中咱们是须要申请多少的资源,是哪一个进程申请,因此咱们须要定义个request二维数组,进行一个资源的申请,行为进程pnum列为资源rnum
这时候,看了我前面的应该知道,咱们须要进行一个建立,咱们最大资源是多少,有多少个进程什么什么的,这些能够根据书上的已知条件,从而知道咱们有多少数据须要用户进行一个输入。数据结构
基本思想:将max,allocation,need,available数组装载数值,有些是一维,有些是二维,根据书上的已知条件能够获得如何建立,这里可能有些读者没书,在此给出代码函数
//初始化 void creat(){ for(int i = 0;i<pnum;i++){ cout<<"请输入第 "<<i<<" 个进程的数据:"<<endl; cout<<"MAX:第"<<i<<"个进程一共须要申请多少个资源(A B C):"; for(int j=0;j<rnum;j++) cin>>Max[i][j]; cout<<"Allocation:已得到的资源数量(A B C): "; for(int j=0;j<rnum;j++) cin>>Allocation[i][j]; cout<<"Need:还须要的资源数量(A B C): "; for(int j=0;j<rnum;j++) cin>>Need[i][j]; if(i==0){ cout<<"Available:现有资源的数量(A B C): "; for(int j = 0;j < rnum;j++) cin>>Available[j]; } } }
这时候咱们回到咱们的main,建立好了以后咱们须要输入request数组中是哪一个进程申请资源数量为多少,为了让读者阅读方便,在此也给出代码测试
while(true){ cout<<endl<<"请输入Request[进程标号i][资源类型j]:"<<endl; cout<<"进程i=:"; cin>>i; cout<<"各种资源数量(A B C): "; for(int j = 0;j < rnum;j++) cin>>Request[i][j]; cout<<endl; //执行银行家算法 int res = Banker(i,Request); //输出每次判断产生的执行序列 cout<<endl<<"当前的资源分配表:"<<endl; show(res); }
你会发现有banker里面的参数是进程几申请资源,最终返回的结果用来输出,那么咱们的show应该如何的进行定义呢?
咱们得显示咱们的资源分配表,若是说安全性算法后还有一个安全队列,咱们得输出安全性队列下的work等一系列,若是没有,咱们就输出咱们各个进程初始信息,all+need+available。让用户明白本身的申请的问题出错在哪。操作系统show:资源分配表的定义
首先show函数得接收一个值,res,表示有无安全序列,若是有,就是个人进程数,若是没有,就是不能构成安全序列咱们须要输出它的初始信息
这里直接给源码,但愿读者读懂后能够评论区留言说说你的理解code
void show(int res){ if(res == pnum){ cout<<" 进程号--"<<" Work[A,B,C]" <<" Need[A,B,C]"<<" Allocation[A,B,C]"<<" Work+Allocation[A,B,C]"<<" Finish"<<endl; for(int i = 0;i < pnum;i++) { for(int j = 0;j < rnum;j++) cout<<work[sign[i]][j]<<" "; cout<<'\t'<<'\t'; for(int j = 0;j < rnum;j++) cout<<Need[sign[i]][j]<<" "; cout<<'\t'<<'\t'; for(int j = 0;j < rnum;j++) cout<<Allocation[sign[i]][j]<<" "; cout<<'\t'<<'\t'; for(int j = 0;j < rnum;j++) cout<<workAll[sign[i]][j]<<" "; cout<<'\t'<<'\t'; cout<<"true"<<endl; } cout<<endl<<"安全序列为:{p["<<sign[0]<<"]"; for(int m = 1;m<pnum;m++){ cout<<",p["<<sign[m]<<"]"; } cout<<"}"<<endl; } else{//没经过输出信息 cout<<" 进程号--"<<" Allocation[A,B,C]" <<" Need[A,B,C]"<<" Available[A,B,C]"<<endl; for(int k = 0;k < 5;k++){ cout<<'\t'<<"P["<<k<<"]"<<'\t'<<'\t'; for(int j = 0;j < 3;j++)cout<<Allocation[k][j]<<" "; cout<<'\t'<<'\t'; for(int j = 0;j < 3;j++)cout<<Need[k][j]<<" "; cout<<'\t'<<'\t'; if(k == 0) { for(int j = 0;j < 3;j++) cout<<Available[j]<<" "; } cout<<endl; } } }
如今进入正题队列
银行家算法banker(i,request[][rnum])
基本思想:第一步,//判断request内的资源是否比可用总数和进程i总共所需的大小,这是基本的条件
如何的实现呢?
for(int j = 0;j < rnum;j++) { if(Request[i][j] > Need[i][j]){ cout<<"分配失败------>"<<endl<<"所需资源数超出其宣布的最大值!"<<endl; return 0; } else if(Request[i][j] > Available[j]) { cout<<"分配失败------>"<<endl<<"无足够资源,p["<<i<<"]须要进行wait"<<endl; return 0; } }
若是经过了,咱们试着分配资源,进行安全性算法,若是没经过就直接返回了error,也会输出提示信息。
首先让资源总数available减去request,让进程的allocation加上申请的,need也须要减去request。
大体理解:由于你申请了资源如今在假定分配,因此分配给你了系统的可用资源就要减小,当前进程的已用资源就要增长,目前还需资源就也要减小,由于系统已经知足你的需求了。
for(int j = 0;j < rnum;j++) { Available[j] = Available[j] - Request[i][j]; Allocation[i][j] = Allocation[i][j] + Request[i][j]; Need[i][j] = Need[i][j] - Request[i][j]; }
执行安全性算法,根据安全性算法的返回值,肯定是否有队列,最终输出显示的状况
后续代码我只给出执行安全性算法,如何让系统交互作的更好留给读者。
int n = Safe(Available,Need,Allocation); cout<<endl; if(n == pnum) {//有5个'true'返回1,表示此时刻安全
咱们为了方便运算,原来的work为了存放available总数加上释放,因此咱们这里新建一个work数组,它是一维的,由于它只须要将一组的数据进行一个传递,finish数组的定义为了判断是否有一个队列,因此它的大小为pnum。这里给出定义,ijmn是根据个人需求进行一个添加
int Safe(int Available[],int Need[][rnum],int Allocation[][rnum]) { int i=0,j=0,m=0,n=0; int Work[rnum],Finish[pnum] = {0,0,0,0,0};
接下来咱们将咱们的可用资源数目给咱们的work临时一维数组。
进入一个大while,只要咱们的i<进程总数pnum咱们就继续在循环中找。这里你应该明白i是为了计数,看看有无这么多的进程完成,若是实在没有咱们的扫描也会结束,到时候finish和i的值都不是理想值
只要对应的finish[i]是等于0 的说明尚未被加入就绪队列,首先判断现有的资源总量可否知足它的需求,能够知足咱们就进行一个分配。这里分配后直接释放了,因此咱们能够直接让work加上allocation中当前i进程的已用资源allocation,在这以前用咱们的work二维数组记录下咱们当前的work再去加进行一个变化,这样在循环中,work中就是显示未释放的状态中的可用资源,让咱们的workall等于咱们的一维数组work,有些许绕,我附上小部分的代码,但愿读者钻研一下。
if(j == rnum){//若是need的三个资源均可以被知足,就分配而且释放和记录 for(int k = 0;k < rnum;k++){ work[i][k] = Work[k];//记录分配前的可用的资源总数 Work[k] = Work[k]+Allocation[i][k]; workAll[i][k] = Work[k]; }
若是咱们这一步成功了,说明是能够分配的,让咱们的安全序列数组sign中的第一个m变成i。finish[i]=1,i=-1,m++.
i 等于-1是由于在咱们的if(Finish[i]==0){后还有一段代码,咱们慢慢分析
咱们是从头开始扫描,因此若是没加入,或者已经加入过了咱们必须让咱们的i++,让咱们的j(用于检查可用资源是否知足的一个变量)归零。因此在if中咱们的i=-1,在外++就变成了0,就是继续从首部查找。
最终根据finish中是否有0,咱们能够获得咱们是该返回pnum仍是其余数字了。
到此已经讲述完了,但愿读者可以仔细思考一下问题,后续结果有人提问我再在评论区更新!!!