前言
hnust操作系统课程设计,其他题目较为简单,可参考其他优秀博主的文章,这里仅介绍两道题
- 简单 shell 命令行解释器的设计与实现
- 银行家算法改进实现
本篇为银行家算法改进实现
白嫖容易,创作不易,若大家认为有用,学到东西,不妨点个赞
博客原创,转载请注明出处
附上另一篇博客链接:简单 shell 命令行解释器的设计与实现
仅用于学习,如有侵权,请联系删除
注意:程序中仍有不足点,例如并未实现多个进程同时请求时需要选择调度其中一个,有兴趣的同学可以自行更改
实验题目
将银行家算法改进为动态不断请求形式
实验目的
本实验主要目的在于进一步理解真正的银行家算法,并且处理实际意义情况下的银行家算法,将其改进为动态情况。
设计内容和要求
要设计的功能必须支持以下情况:
(1)首先要设置好总资源数量;
(2)新进程申请时需要输入其max(claim)资源数量(必须小于总资源数);
(3)新进程申请尝试分配后,更新状态,不成立则阻塞,成立则分配;
(4)老进程可能再次申请;
(5)老进程申请后需要判定结束,若结束则需判定阻塞的进程是否能转为就绪态;
(6)静态申请改为动态申请,结束需要回收数组;
(7)阻塞队列中可以加入算法;
总体设计
流程图:
算法步骤:
使用了C++的vector的一些方法,若不明白可以自行查阅资料
首先是一个无限循环。
-
首先在main函数中,我们需要设置一个无限循环,不断让用户进程申请
-
输入进程编号后检测是否为老进程,若不是则需要输入最大申请资源数
printf("请输入需要申请的进程编号:\n"); cin >> num; res.number = num; vector<int>::iterator iter=find(vec.begin(),vec.end(),num); if(iter==vec.end())//未找到 { cout << "未查找到老进程P" << num << endl; vec.push_back(num); printf("请输入P%d进程所需资源总数(claim):\n",num); cin >> res.a >> res.b >> res.c; claim.push_back(res); max_claim.push_back(res); }
-
输入此次申请资源数
-
检测是否会阻塞,若阻塞则加入阻塞队列,否则进行分配资源
if(checkBlock(num))//checkBlock检测是否会阻塞 { cout << "允许P" << num << "进程分配资源" << endl; nowClaim = findClaim();//查找当前进程最大申请量 if(safeQueue(nowClaim)) flag=true; //某进程结束,释放资源 else { if(block.size()==0) flag=false;//未释放资源且阻塞队列为空则重新输入(避免阻塞队列中取出一个后就不管剩下阻塞的进程了) } cout << "当前资源剩余量:" << RESOURCE[0] << " " << RESOURCE[1] << " " << RESOURCE[2] << endl; } else //阻塞 { res.a = request[0]; res.b = request[1]; res.c = request[2]; block.push_back(res); }
-
分配资源时判断是否进程结束(达到最大进程申请资源数),若满足则释放资源,否则继续输入新进程申请
bool safeQueue(int nowClaim)//分配资源 { //允许分配资源,调整资源值 if(flag)//表示阻塞队列中的一个进程转为就绪态进行分配资源 { request[0] = block[0].a; request[1] = block[0].b; request[2] = block[0].c; std::vector<resource>::iterator it4 = block.begin(); block.erase(it4);//将其从阻塞队列中删除 } for(int j=0;j<3;j++) RESOURCE[j]-=request[j]; claim[nowClaim].a-=request[0]; claim[nowClaim].b-=request[1]; claim[nowClaim].c-=request[2]; if(claim[nowClaim].a==0&&claim[nowClaim].b==0&&claim[nowClaim].c==0) { cout << "进程P" << claim[nowClaim].number << "结束,释放资源" << endl; std::vector<int>::iterator it = vec.begin(); std::vector<resource>::iterator it1 = claim.begin(); std::vector<resource>::iterator it2 = max_claim.begin(); it=vec.begin()+nowClaim; it1=claim.begin()+nowClaim; it2=max_claim.begin()+nowClaim; vec.erase(it); claim.erase(it1);//表示释放资源,该进程结束 RESOURCE[0]+=max_claim[nowClaim].a; RESOURCE[1]+=max_claim[nowClaim].b; RESOURCE[2]+=max_claim[nowClaim].c; max_claim.erase(it2); return true; } else return false; }
-
若释放资源,则需要判断阻塞队列是否有满足的进程,将所有满足的进程都分配资源,并重复上述检测是否结束的步骤
else//表示上次分配资源后有进程结束释放资源,需要检测阻塞队列 { if(!allocBlock()) { flag = false;//如果阻塞队列没有符合进程则下次不用检测阻塞队列,反之下次继续 continue; } cout << "P" << num << "进程由阻塞态转为就绪态" << endl; }
实验结果分析
由上述结果可以看出,实现了,遇到老进程再次申请资源时,会判断是否满足该进程最大申请量(max),若满足则表示进程可以结束,释放资源,每次释放资源后,检查阻塞队列中是否有满足条件的进程,若满足则转为就绪态进行资源分配,同时在阻塞队列中进行了排序,按照申请资源数量从小到大排序,每次只需要检测第一个即可
小结与心得体会
此次实验总体并不难,利用C++ vector可以实现动态申请资源,其中需要考虑到动态后还需要释放内存,同时,在每次进程申请时都要判断其是否满足释放资源条件,满足则释放,释放后需要检测阻塞队列,将队列中每个满足的进程都转为就绪态,其中阻塞队列中使用了一个简单的排序算法,方便进行进程调度。
源码如下:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
struct resource
{
int number;//进程编号
int a;
int b;
int c;
};
int RESOURCE[3];//存储资源总数
int request[3];//存储各进程每次申请资源数
int num;//进程编号
bool flag=false;//判断是否需要检测阻塞队列
int nowClaim;//查找当前进程最大申请量所对应claim中的下标
vector<int> vec;//判断是老进程还是新进程
vector<resource> claim;//存储各进程最大需求
vector<resource> max_claim;//存储各进程最大需求
vector<resource> block;//存储各进程最大需求
bool checkBlock(int num)//判断num进程是否阻塞
{
for(int j=0;j<3;j++)
{
if(request[j]>RESOURCE[j])
{
cout << "P" << num << "进程此次请求超过最大资源数,阻塞!" << endl;
return false;
}
}
return true;
}
bool safeQueue(int nowClaim)//分配资源
{
//允许分配资源,调整资源值
if(flag)//表示阻塞队列中的一个进程转为就绪态进行分配资源
{
request[0] = block[0].a;
request[1] = block[0].b;
request[2] = block[0].c;
std::vector<resource>::iterator it4 = block.begin();
block.erase(it4);//将其从阻塞队列中删除
}
for(int j=0;j<3;j++) RESOURCE[j]-=request[j];
claim[nowClaim].a-=request[0];
claim[nowClaim].b-=request[1];
claim[nowClaim].c-=request[2];
if(claim[nowClaim].a==0&&claim[nowClaim].b==0&&claim[nowClaim].c==0)
{
cout << "进程P" << claim[nowClaim].number << "结束,释放资源" << endl;
std::vector<int>::iterator it = vec.begin();
std::vector<resource>::iterator it1 = claim.begin();
std::vector<resource>::iterator it2 = max_claim.begin();
it=vec.begin()+nowClaim;
it1=claim.begin()+nowClaim;
it2=max_claim.begin()+nowClaim;
vec.erase(it);
claim.erase(it1);//表示释放资源,该进程结束
RESOURCE[0]+=max_claim[nowClaim].a;
RESOURCE[1]+=max_claim[nowClaim].b;
RESOURCE[2]+=max_claim[nowClaim].c;
max_claim.erase(it2);
return true;
}
else return false;
}
int findClaim()//查找num进程对应最大申请量下标
{
for(int i = 0;i<claim.size();i++)
{
if(claim[i].number == num) return i;
}
return -1;
}
bool comp(const resource r1, const resource r2)//排序比较器
{
return (r1.a+r1.b+r1.c) < (r2.a+r2.b+r2.c);
}
bool allocBlock()//检查阻塞队列是否能分配资源
{
if(block.size()==0) return false;
sort(block.begin(),block.end(),comp);//将阻塞队列排序
if(block[0].a<RESOURCE[0]&&block[0].b<RESOURCE[1]&&block[0].c<RESOURCE[2])
{
num = block[0].number;//将num刷新,方便接下来分配资源
return true;
}
return false;
}
int main()
{
resource res;
printf("请输入资源总数(Resource):(a,b,c)\n");
scanf("%d%d%d",&RESOURCE[0],&RESOURCE[1],&RESOURCE[2]);
while(true)
{
if(!flag)//表示不需要检测阻塞队列
{
printf("请输入需要申请的进程编号:\n");
cin >> num;
res.number = num;
vector<int>::iterator iter=find(vec.begin(),vec.end(),num);
if(iter==vec.end())//未找到
{
cout << "未查找到老进程P" << num << endl;
vec.push_back(num);
printf("请输入P%d进程所需资源总数(claim):\n",num);
cin >> res.a >> res.b >> res.c;
claim.push_back(res);
max_claim.push_back(res);
}
printf("请输入进程P%d申请的资源数量:(request)(不可超过最大申请资源数claim)\n",num);
nowClaim = findClaim();//查找当前进程最大申请量的下标
cout << "nowClaim = " << nowClaim << endl;
if(nowClaim>=0) printf("P%d进程最大申请资源数为:%d %d %d\n",num,claim[nowClaim].a,claim[nowClaim].b,claim[nowClaim].c);
cin >> request[0] >> request[1] >> request[2];
}
else//表示上次分配资源后有进程结束释放资源,需要检测阻塞队列
{
if(!allocBlock())
{
flag = false;//如果阻塞队列没有符合进程则下次不用检测阻塞队列,反之下次继续
continue;
}
cout << "P" << num << "进程由阻塞态转为就绪态" << endl;
}
if(checkBlock(num))//checkBlock检测是否会阻塞
{
cout << "允许P" << num << "进程分配资源" << endl;
nowClaim = findClaim();//查找当前进程最大申请量
if(safeQueue(nowClaim)) flag=true; //某进程结束,释放资源
else
{
if(block.size()==0) flag=false;//未释放资源且阻塞队列为空则重新输入(避免阻塞队列中取出一个后就不管剩下阻塞的进程了)
}
cout << "当前资源剩余量:" << RESOURCE[0] << " " << RESOURCE[1] << " " << RESOURCE[2] << endl;
}
else //阻塞
{
res.a = request[0];
res.b = request[1];
res.c = request[2];
block.push_back(res);
}
}
}