实验2 银行家算法的实现
文章目录
一、实验内容
银行家算法的实现。
二、实验目的
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。通过编写一个模拟动态资源分配的银行家算法程序,帮助学生进一步深入理解死锁、产生死锁的必要条件、安全状态等重要概念,并掌握避免死锁的具体实施方法。
三、实验原理
3.1、银行家算法中的数据结构
(1)可利用资源向量(Available)
是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。
(2)最大需求矩阵(Max)
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
(3)分配矩阵(Allocation)
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
(4)需求矩阵(Need)
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]
3.2、银行家算法
设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1)如果Requesti[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布最大值。
(2)如果Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,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];
系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程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[j]+ Allocation[i,j];
Finish[i]= true;
go to step 2;
(4)如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。
四、算法流程图
五、源程序及注释
#include <bits/stdc++.h>
using namespace std;
#define processNum 5//进程数
#define resourceNum 3//资源类别
int p;//初始状态
int work[resourceNum];//系统中的可用资源
int Request[resourceNum];//请求的各类资源
bool Finish[processNum];//判断各类资源是否用完
int Available[resourceNum];//可利用资源
int Max[processNum][resourceNum];//最大的需求
int Need[processNum][resourceNum];//需求矩阵
int Allocation[processNum][3];//分配矩阵
void init(){
cout <<"手动输入测试数据" << endl;
for(int i = 0; i < resourceNum; i++)
cin >> Available[i];//输入可利用资源
for(int i = 0; i < processNum; i++)
for(int j = 0; j < resourceNum; j++)
cin >> Max[i][j];//输入可利最大的需求
for(int i = 0; i < processNum; i++)
for(int j = 0; j < resourceNum; j++)
cin >> Need[i][j];//输入需求矩阵
for(int i = 0; i < processNum; i++)
for(int j = 0; j < 3; j++)
cin >> Allocation[i][j];//输入分配矩阵
}
/*测试数据
3 3 2
7 5 3 3 2 2 9 0 2 2 2 2 4 3 3
7 4 3 1 2 2 6 0 0 0 1 1 4 3 1
0 1 0 2 0 0 3 0 2 2 1 1 0 0 2
*/
//输出初始化的信息表
void print1(){
cout <<"系统剩余资源数:"<< endl;
for(int j = 0;j < resourceNum;j++)
cout << Available[j] << "\t";
cout << endl;
cout << "——————前资源分配状态——————" << endl;
cout << "process——Max——Allocation——Need" << endl;
for(int i = 0;i < processNum;i++){
cout << "p" << i << "\t";
for(int j = 0;j < resourceNum;j++)
cout << Max[i][j] << " ";//输出进程需要的最大需求量
cout << "\t";
for(int j = 0;j < resourceNum;j++)
cout << Allocation[i][j] << " ";//输出进程的各类资源的分配
cout << "\t";
for(int j = 0;j < resourceNum;j++)
cout << Need[i][j] << " ";//输出各类资源仍需要的资源数目
cout << endl;
}
}
void print2(int i){
int j;
if(Need[i][0] == 0 && Need[i][1] == 0 && Need[i][2] == 0){
for(int k = 0; k < resourceNum; k++){
work[k] += Allocation[i][k];
Available[k] += Allocation[i][k];
}
}
cout << "p" << i << "\t";
for(j = 0; j < resourceNum; j++)
cout << work[j];//输出系统中的可用资源
cout << "\t"
for(j = 0; j < resourceNum; j++)
cout << Need[i][j];//输出各类资源仍需要的资源数目
cout << "\t";
for(j = 0; j < resourceNum; j++)
cout << Allocation[i][j];//输出进程的各类资源的分配
cout << "\t";
for(j = 0; j < resourceNum; j++)
cout << work[j];
cout << "\t";
for(j = 0; j < resourceNum; j++)
if(!Finish[i]) break;
if(j == resourceNum) cout << "True\t" << endl;
else cout << "False\t" << endl;
}
//进程不安全,回收预分配的资源
void recycle(){
int j;
for(j = 0;j < resourceNum;j++){
Need[p][j] += Request[j];
Available[j] += Request[j];
Allocation[p][j] -= Request[j];
}
cout << "系统进程资源状态不改变!" <<endl;
}
//检测分配是否安全
void Test_safety(){
int i,j,te;
int finish = 0,Done = 0; //Done一轮遍历下完成的,finish总共完成的
int safeseries[processNum] = {-1,-1,-1,-1,-1};
//初始化
for(i = 0;i < processNum;i++)
Finish[i] = false;
for(j = 0;j < resourceNum;j++)
work[j] = Available[j]; //初始值等于Available;
// 查找未完成进程,且当前进程尚需资源不大于系统剩余资源;
i = 0;
while(finish != processNum){
j = 0;
if(Finish[i] == false){//如果这个进程的还需要的各类资源还大于系统当前的资源的;
for(j = 0;j < resourceNum;j++)
if(Need[i][j] > work[j]) break;
}
if(j == resourceNum){//此时代表当前的系统资源可以满足这个进程
//那么可以对这个进程的资源进程回收。
Finish[i] = true;//代表该进程已经被完成。
print2(i);
safeseries[finish++] = i; //记录下安全序列
for(j = 0;j < resourceNum;j++)//开始资源的回收
work[j] += Allocation[i][j];
}
i++; //下一个进程
//一轮遍历后,判断是否还有可分配进程
if(i >= processNum){
i = i % processNum;
if(Done == finish) break;//判断本轮完成进程是否等于上一轮,是则代表没有可执行进程
else Done = finish; //否则将本轮完成进程数赋值给Done
}
}
if(finish == processNum){
printf("进程P%d请求通过,此时安全序列为:",p);
for(i = 0;i < processNum;i++)
cout << safeseries[i];
cout << endl;
print1(); //打印出此刻系统资源分配状态
}else{
recycle();
printf("进程死锁,进程P%d请求无法通过!\n",p);
print1();
}
}
void judge_assign(){
int j;
for(j = 0;j < resourceNum;j++){
//当前请求资源加上已分配资源不能大于最大需求资源;
if(Request[j] + Allocation[p][j] > Max[p][j]){
cout <<"当前请求资源+已分配资源>最大需求资源:无法满足!错误!"<< endl;
break;
}
//当前请求资源不能大于系统现有资源;
if(Request[j] > Available[j]){
cout <<"当前请求资源>系统现有资源:无法满足!错误!"<< endl;
break;
}
}
if(j == resourceNum){
//尝试分配资源
for(j = 0;j < resourceNum;j++){
Need[p][j] -= Request[j];
Available[j] -= Request[j];
Allocation[p][j] += Request[j];
}
//检查此时系统的安全性
cout << "——————安全序列——————" << endl;
cout << "process——Work——Need——Allocation——work+allocation——finish"<< endl;
Test_safety();
}
}
int main(){
init();
print1();
cout << "——————此时安全序列——————" << endl;
cout << "process——Work——Need——Allocation——work+allocation——finish"<< endl;
Test_safety();
while(1){
cout << "存在进程0,1,2,3,4,资源类别0,1,2\n请依次输入请求资源的进程和进程请求的A,B,C类资源数\n例如:1 0 0 1" << endl;
cin >> p;
for(int i = 0;i < resourceNum;i++)
cin >> Request[i];
judge_assign();//尝试分配资源给进程
}
return 0;
}
六、打印的程序运行时初值和运行结果
七、实验小结
通过本次实验初步实现了对银行家算法的模拟,要求实现的功能较多,故实际实践起来有一定困难,实验课上时间内未完成,在课余时间修改调试。程序中大多使用全局数组为了方便程序调用,因而没有实现手动输入控制进程个数和资源种类个数,只能对宏定义进行修改达到目的。空闲时间会进一步对细节方面进行完善和优化。