银行家算法:
主要考虑进程能不能正常分配的问题,即剩余资源该先分配谁,分配了后能不能让它执行完,执行完返回的资源又该继续分给谁的问题,最后看能不能所有进程都分配到资源执行完。执行完了会有安全序列
但是安全序列不唯一!
主要逻辑:
第一点:进程初始化的时候 Allocation资源 <= Max资源; Need+Allocation资源 <= MAX资源 这个是必须要保证的,超过了就没意义了。
第二点:当第一次执行算法时就无法得出安全序列,则不用考虑有别的进程临时申请资源了!
第三点:当首次算法执行完后,能得出安全序列,能首次Request资源时用的资源表是初始化的资源表这是要理清楚的,后面Request申请的则用上一次的资源申请表所以要考虑好资源表的保存以及复用,还有要做好Allocation,Need,Available的保存,复用以及还原,要做还原这个在下一点讲。
第四点:进程临时资源申请有两大条件需要满足 ①Request<=Need ②Request<=Available
当进程满足这两个条件时,Allocation + Request;Need - Request; Available - Request;但是当资源满足但又无法得出安全序列的时候则需要把这些都复原,即上述所说要做好原资源量的保存
代码区:
#include<iostream>
#include<queue>
using namespace std;
struct PCB {
string Name;
int Max[1][3];
int Allocation[1][3];
int Need[1][3];
int Work[1][3];
int endResource[1][3];//Work+Allocation
string finish;
};
int Available[1][3];
int reAvailable[1][3];
int useCount = 0;
queue<PCB>readList;
queue<PCB>temp_ReadList;
//显示录入数据的当前量
void showInitData(queue<PCB>q) {
queue<PCB>temp;
temp = q;
cout << "------------------------------------------数据初始状态------------------------------------------" << endl;
cout << "进程名\t" << "进程Max量\t" << "进程Allcation量\t" << " 进程Need量\t" << " 进程Work\t" << " 进程状态" << endl;
while (q.size() != 0) {
cout << q.front().Name << "\t " << q.front().Max[0][0] << " " << q.front().Max[0][1] << " " << q.front().Max[0][2] << "\t\t "
<< q.front().Allocation[0][0] << " " << q.front().Allocation[0][1] << " " << q.front().Allocation[0][2] << "\t\t"
<< q.front().Need[0][0] << " " << q.front().Need[0][1] << " " << q.front().Need[0][2] << "\t\t"
<< q.front().Work[0][0] << " " << q.front().Work[0][1] << " " << q.front().Work[0][2] << "\t "
<< q.front().finish << endl;
q.pop();
}
cout << "------------------------------------------------------------------------------------------------" << endl;
q = temp;
}
//展示能否成功执行
void showData(queue<PCB>& q) {
queue<PCB>temp;
temp = q;
cout << "------------------------------------------数据完毕状态------------------------------------------" << endl;
cout << "进程名\t" << "进程Work量\t" << "进程Need量\t" << "进程Allcation量\t" << " 进程Work+Allocation\t" << "进程状态" << endl;
while (q.size() != 0) {
cout << q.front().Name << "\t " << q.front().Work[0][0] << " " << q.front().Work[0][1] << " " << q.front().Work[0][2] << "\t\t "
<< q.front().Need[0][0] << " " << q.front().Need[0][1] << " " << q.front().Need[0][2] << "\t "
<< q.front().Allocation[0][0] << " " << q.front().Allocation[0][1] << " " << q.front().Allocation[0][2] << "\t\t"
<< q.front().endResource[0][0] << " " << q.front().endResource[0][1] << " " << q.front().endResource[0][2] << "\t\t "
<< q.front().finish << endl;
q.pop();
}
cout << "------------------------------------------------------------------------------------------------" << endl;
q = temp;
}
//输出安全序列
void showSafeQueue(queue<PCB>& q) {
queue<PCB>temp;
temp = q;
cout << "安全序列为:";
while (q.size() != 0) {
cout << q.front().Name;
q.pop();
if (q.size() != 0) {
cout << "->";
}
}
cout << endl;
q = temp;
}
void InitPCB() {
PCB p;
int sum;
cout << "请输入进程个数:";
cin >> sum;
for (int i = 1; i <= sum; i++) {
cout << "请输入进程名字:";
cin >> p.Name;
cout << "请输入" << p.Name << "所需的最大资源量Max例如(1 2 3):";
cin >> p.Max[0][0] >> p.Max[0][1] >> p.Max[0][2];
cout << "请输入" << p.Name << "已分配的资源量Allocation例如(1 2 3):";
while (1) {
cin >> p.Allocation[0][0] >> p.Allocation[0][1] >> p.Allocation[0][2];
if ((p.Max[0][0] < p.Allocation[0][0]) < (p.Max[0][1] < p.Allocation[0][1]) || (p.Max[0][2] < p.Allocation[0][2])) {
cout <<p.Name<< "的Allocation输入有误不能大于Max资源量!!!请重新输入格式(1 2 3):" << endl;
cin >> p.Allocation[0][0] >> p.Allocation[0][1] >> p.Allocation[0][2];
}
else {
break;
}
}
cout << "请输入" << p.Name << "还需要申请的资源量Need例如(1 2 3):";
while (1) {
cin >> p.Need[0][0] >> p.Need[0][1] >> p.Need[0][2];
if ((p.Max[0][0] < p.Allocation[0][0] + p.Need[0][0]) < (p.Max[0][1] < p.Allocation[0][1] + p.Need[0][1]) || (p.Max[0][2] < p.Allocation[0][2] + p.Need[0][2])) {
cout << p.Name << "的Need输入有误Allocation+Need不能大于Max资源量!!!请重新输入格式(1 2 3):" << endl;
cin >> p.Need[0][0] >> p.Need[0][1] >> p.Need[0][2];
}
else {
break;
}
}
p.Work[0][0] = p.Work[0][1] = p.Work[0][2] = 0;
p.endResource[0][0] = p.endResource[0][1] = p.endResource[0][2] = 0;
p.finish = "false";
//放入容器中
readList.push(p);
}
//作为永久的一个数据存储量 不改变的。
temp_ReadList = readList;
//显示录入值的情况
showInitData(readList);
}
//只查找有没有这个名字
//防止有人输错名字;
bool Find_Name(string name, queue<PCB>& q) {
string endName;
//最后一个数据的名字
endName = q.back().Name;
while (q.size()!=0) {
if (name == q.front().Name) {
return true;
}
else {
if (q.front().Name == endName) {
return false;
}
q.push(q.front());
q.pop();
}
}
}
//按名字查找并做操作
bool Find_PCB_ofName(string name,queue<PCB>& q) {
if (name == q.front().Name) {
//进程资源申请两大因素。1、Request量<=进程需求量 2、Request量<=初始工作资源量
if (((q.front().Need[0][0] >= reAvailable[0][0]) && (q.front().Need[0][1] >= reAvailable[0][1])
&& (q.front().Need[0][2] >= reAvailable[0][2])) && ((Available[0][0] >= reAvailable[0][0])
&& (Available[0][1] >= reAvailable[0][1]) && (Available[0][2] >= reAvailable[0][2]))) {
//当条件满足则把当前进程名的需求量 - 申请量
q.front().Need[0][0] = q.front().Need[0][0] - reAvailable[0][0];
q.front().Need[0][1] = q.front().Need[0][1] - reAvailable[0][1];
q.front().Need[0][2] = q.front().Need[0][2] - reAvailable[0][2];
//当前进程名的拥有量 + 申请量
q.front().Allocation[0][0] = q.front().Allocation[0][0] + reAvailable[0][0];
q.front().Allocation[0][1] = q.front().Allocation[0][1] + reAvailable[0][1];
q.front().Allocation[0][2] = q.front().Allocation[0][2] + reAvailable[0][2];
showInitData(q);
return true;
}
else {
return false;
}
}
}
bool Algorithm_PCB( int Available[1][3], queue<PCB>& q) {
queue<PCB>noSafe;
noSafe = q;
queue<PCB>endList;
int count = 0;
int tempSize=q.size();//查看是否能达到原来队列的总数,如果能则有最少一条安全序列,如果不能则没有安全序列
for (int i = 0; i < tempSize; i++) {
while (q.size() != 0) {
//判断Available是否足够分配给Need的每一部分
if ((Available[0][0] >= q.front().Need[0][0]) && (Available[0][1] >= q.front().Need[0][1]) && (Available[0][2] >= q.front().Need[0][2])) {
//把剩余资源里分到work里记录
q.front().Work[0][0] = Available[0][0];
q.front().Work[0][1] = Available[0][1];
q.front().Work[0][2] = Available[0][2];
//满足条件的话就进行工作预算
q.front().endResource[0][0] = Available[0][0] + q.front().Allocation[0][0];
q.front().endResource[0][1] = Available[0][1] + q.front().Allocation[0][1];
q.front().endResource[0][2] = Available[0][2] + q.front().Allocation[0][2];
//改变当前拥有的资源量
Available[0][0] = q.front().endResource[0][0];
Available[0][1] = q.front().endResource[0][1];
Available[0][2] = q.front().endResource[0][2];
//完成置换标志位
q.front().finish = "true";
endList.push(q.front());
count++; //防止死循环用
if (count % tempSize == 0) {
count = 0;
break;
}
q.pop();
break;
}
else {
count++;//防止死循环用 只在这里设置会崩溃 没办法只能用两个
if (count % tempSize==0) {
count = 0;
break;
}
q.push((q.front()));
q.pop();
}
}
//count == 0;
}
//如果出来量跟原始的队列量相同则有安全序列,如果不同则没有安全序列
if (endList.size() == tempSize) {
showData(endList);
showSafeQueue(endList);
return true;
}
else {
q = noSafe;
cout << "没有安全序列!!" << endl;
cout << "--------------------没有安全序列还没返回资源的情况--------------------" << endl;
cout << "没有安全序列当前Available:" << Available[0][0] << " " << Available[0][1] << " " << Available[0][2] << endl;
cout << "---------------------------------------------------------------------" << endl;
showInitData(q);
return false;
}
}
void Continue_Algorithm(queue<PCB>& q) {
//做数据量保存操作 后续可以一直申请
int tempCountinueAvailable[1][3];
string flag;
//是否继续操作
while (1) {
cout << "是否有进程申请资源yes/no:";
cin >> flag;
//判断输入的flag是否正确
while (1) {
if (flag == "yes" || flag =="YES" || flag == "no" || flag == "NO") {
break;
}
else {
cout << "输入有误,请重新输入yes/no:";
cin >> flag;
}
}
//如果输入正确就继续执行下一步
if (flag == "yes" || flag == "YES") {
cout << "请输入申请的Available值如(1 2 3):";
cin >> reAvailable[0][0] >> reAvailable[0][1] >> reAvailable[0][2];
string Name;
cout << "是哪个进程申请的:";
cin >> Name;
//考虑进程名是否能正确
while (1) {
if (Find_Name(Name, q) == true) {
//如果正确就不用执行这个
break;
}
else {
cout << "需要分配的进程名有误,请重新输入:";
cin >> Name;
}
}
//找的到名字的话就进行下一步
//先判定能不能正常分配
if (Find_PCB_ofName(Name, q) == true) {
queue<PCB>tempq;
//如果可以正常分配
//先存第一次的资源量:
//找到了名字也要满足资源是是否能分配的情况
tempCountinueAvailable[0][0] = Available[0][0] = Available[0][0] - reAvailable[0][0];
tempCountinueAvailable[0][1] = Available[0][1] = Available[0][1] - reAvailable[0][1];
tempCountinueAvailable[0][2] = Available[0][2] = Available[0][2] - reAvailable[0][2];
//保存当前的所有数据。
tempq = q;
//重复操作计算:
if (Algorithm_PCB(Available, q) == true) {
q = tempq;//把前面保存的刷新一下可以继续让下一次申请资源用。
//把申请后的资源量更新回原状态
Available[0][0] = tempCountinueAvailable[0][0];
Available[0][1] = tempCountinueAvailable[0][1];
Available[0][2] = tempCountinueAvailable[0][2];
cout << "-------------------------------------------------------" << endl;
cout << "初始工作Available:" << Available[0][0] << " " << Available[0][1] << " " << Available[0][2] << endl;
cout << "-------------------------------------------------------" << endl;
showInitData(q);
}
else {
//返回数据
Available[0][0] = reAvailable[0][0] + Available[0][0];
Available[0][1] = reAvailable[0][1] + Available[0][1];
Available[0][2] = reAvailable[0][2] + Available[0][2];
cout << "--------------------没有安全序列返回资源的情况--------------------" << endl;
cout << "当前Available:" << Available[0][0] << " " << Available[0][1] << " " << Available[0][2] << endl;
cout << "------------------------------------------------------------------" << endl;
}
}else {
cout << "-------------------------------------------------------" << endl;
cout << "申请资源条件不满足!" << endl;
cout << "-------------------------------------------------------" << endl;
cout << "-------------------------------------------------------" << endl;
cout << "当前Available:" << Available[0][0] << " " << Available[0][1] << " " << Available[0][2] << endl;
cout << "-------------------------------------------------------" << endl;
showInitData(q);
}
}else {
//如果不用继续执行则退出;
break;
}
}
}
int main() {
InitPCB();
int tempAvailable[1][3];
cout << "请输入Available值如(1 2 3):";
cin >> Available[0][0] >> Available[0][1] >> Available[0][2];
//临时存储
tempAvailable[0][0] = Available[0][0];
tempAvailable[0][1] = Available[0][1];
tempAvailable[0][2] = Available[0][2];
if (Algorithm_PCB(Available, readList) ==true) {
//重置回readList;
//重置剩余量:
Available[0][0] = tempAvailable[0][0];
Available[0][1] = tempAvailable[0][1];
Available[0][2] = tempAvailable[0][2];
readList = temp_ReadList;
//如果第一次能有安全序列,那么有可能还有资源可以申请资源。
Continue_Algorithm(readList);
}
else {
cout << "一开始就没有安全序列!你还想有后续的申请?那是不可能的!" << endl;
}
return 0;
}