前言:
该代码是本人为了应付(其实也有好好敲,而且自我感觉良好)操作系统课程设计而编写滴,全程使用vector代替array,因此感觉会比较适合某些数组操作水平不理想(比如我)的同学.当然,代码本身也存在一些问题,比如安全序列检测部分做的会有一点冗余.其实我个人觉得考虑细致一点蛮好,但我们老师说最好不要这样子啦.不说废话了,先展示一下我的代码总体执行过程:

仔细观察可以发现,我根据预分配资源后该进程能否释放资源,编写了两个安全序列检测函数......虽然冗余,但,问题不大.然后的话这套代码展示效果还是比较好的,且能处理绝大部分异常输入(不敢百分百保证,因为可能有没想到的bug).具体的实现过程如下:
第一部分:确定所需数据结构 (此处假设有m种资源,n个进程)
1_假设共有m种资源会被使用,则需一个大小为m的Available[]向量记录可用于分配的各种资源的数量.(可用static数据类型实现,也可通过分别建立单条记录的类和记录表实现)
2_假设每条记录均可能使用所有的资源,则每条记录需设置一个大小为m的最大需求向量 Max_Need[],用于记录其对各种资源的需求.
3_每条记录需设置一个大小为m的已分配资源向量Allocation[],记录其已经获得的资源数
4_每条记录应设计一个仍需资源向量Need[],其各个位置大小应为Max_Need与Allocation中对应位置的差值.
5_每条记录可以申请资源,因此需设置一个资源申请向量Request[];
6_大小为m的Work矩阵,用于模拟分配资源过程中资源的变化
7_大小为n的Finish矩阵,与Work矩阵配合使用.
第二部分:确定实现模块
我是通过实现资源类、单条进程类、进程表类三个class来实现整个程序的.(直接上源码了,参考着看会舒服一点)
资源类包含关系:

资源类对应定义与函数:
class Resource_Name {
private:
vector<string>resource;
public:
Resource_Name(vector<string>& resource) {
this->resource = resource;
}
Resource_Name() {};
void Show_Resource_Name() {
vector<string>::iterator ed = resource.end();
vector<string>::iterator st = resource.begin();
cout << "资源名称:";
while (st != ed) {
cout << " " << *st;
st++;
}
}
void Create_Resource_Index(vector<string>& resource, int Resource_Num) {
string tem;
for (int i = 0; i < Resource_Num; i++) {
cin >> tem;
resource.push_back(tem);
}
}
~Resource_Name() {};
friend class Basic_Process_Message;
friend class Process_Table;
};
这里为了方便阅读(其实是省事),函数直接写到类的内部了
单条进程类包含关系:

单条进程类对应定义与函数:
class Basic_Process_Message {
private:
string Process_ND;
vector<int>Max_Need; //各个进程的最大需求
vector<int>Allocation; //各个进程的已分配资源
vector<int>Need; //各个进程当前所需的资源数
vector<int>Request; //进程发出请求
Resource_Name rs;
public:
Basic_Process_Message(vector<string>& resource) :rs(resource)
{
int tem;
vector<string>::iterator it = rs.resource.begin();
vector<string>::iterator ed = rs.resource.end();
Request.resize(rs.resource.size());
cin >> Process_ND;
while (it != ed) {
cin >> tem;
if (tem < 0) {
cout << "录入错误!" << endl;
return;
}
Max_Need.push_back(tem);
it++;
}
it = rs.resource.begin();
while (it != ed) {
cin >> tem;
if (tem < 0) {
cout << "录入错误!" << endl;
return;
}
Allocation.push_back(tem);
it++;
}
it = rs.resource.begin();
int j;
for (tem = 0; it != ed; tem++)
{
if ((j = Max_Need[tem] - Allocation[tem]) >= 0) {
Need.push_back(j);
it++;
}
else {
cout << "输入错误!" << endl;
return;
}
}
}
Basic_Process_Message() {};
void ShowMaxNeed() {
for (int i = 0; i < rs.resource.size(); i++)
cout << " " << Max_Need[i];
}
void ShowAlloCation() {
for (int i = 0; i < rs.resource.size(); i++)
cout << " " << Allocation[i];
}
void ShowPresentNeed() {
for (int i = 0; i < rs.resource.size(); i++)
cout << " " << Need[i];
}
bool SendRequest() {
bool flag = true;
int i;
cout << endl << "进程" << Process_ND << "发起资源申请!请依次输入各个资源申请数量!" << endl << endl;
cout << endl;
for (i = 0; i < rs.resource.size(); i++) {
cin >> Request[i];
if (Request[i] > Need[i] || Request[i] < 0)
flag = false;
}
if (flag == false) {
cout << "申请资源有误,拒绝本次资源申请!" << endl;
}
else {
cout << endl << "进程" << Process_ND << "资源申请情况如下:" << endl << endl;
for (i = 0; i < rs.resource.size(); i++)
cout << "申请资源" << rs.resource[i] << "的数量: " << Request[i] << endl << endl;
}
return flag;
}
~Basic_Process_Message() {};
friend class Process_Table;
};
进程表类包含关系:
进程表类对应定义与函数:
class Process_Table {
public:
vector<int>Available;
vector<bool>Finish; //判断假设经过一次资源分配,所有进程是否还存在一个安全序列
vector<Basic_Process_Message>ProcessTable;
vector<int>Work;
int Safe_Flag;
public:
Process_Table(vector<Basic_Process_Message>& bpm, int Process_Num) { //此处完成进程表的初始化!
int tem;
int j;
ProcessTable = bpm; //进程表创建完毕
Safe_Flag = 1;
for (tem = 0; tem < Process_Num; tem++) {
Finish.push_back(false); //初始化Finish矩阵
}
bpm[0].rs.Show_Resource_Name(); //这里做的不是很好,每一个向量都可以展示资源,而且是属于难以改进的那种
cout << endl << endl;
for (tem = 0; tem < bpm[0].rs.resource.size(); tem++) {
cin >> j;
Available.push_back(j);
}
Work = Available; //Work数组的初始化
}
void Initial_Process_Index(vector<Basic_Process_Message>& bpm, //初始化进程数组表
int Process_Num, vector<string>& resource, int Resource_Num) {
Basic_Process_Message* Basic_pm;
for (int i = 0; i < Process_Num; i++) {
Basic_pm = new Basic_Process_Message(resource);
bpm.push_back(*Basic_pm);
}
}
Process_Table() {}
void Show_Table_Data() { //仅展示进程表内部信息
cout << " 进程名称 " << "Max_Need " << " Allocation " << " Need " << endl << endl;
for (int i = 0; i < ProcessTable.size(); i++) {
cout << " " << ProcessTable[i].Process_ND << " ";
ProcessTable[i].ShowMaxNeed();
ProcessTable[i].ShowAlloCation();
ProcessTable[i].ShowPresentNeed();
cout << endl << endl;
}
}
void Show_Resource_Can_Be_Used() {
cout << endl << " 可用资源数: ";
for (int i = 0; i < Available.size(); i++)
cout << Available[i] << " ";
cout << endl;
}
void ShowFinish_Data() {
cout << endl << " Finish状态: ";
for (int i = 0; i < Finish.size(); i++)
cout << Finish[i] << " ";
cout << endl << endl;
}
void ShowWorkData() {
cout << endl << " Work状态: ";
for (int i = 0; i < Work.size(); i++)
cout << Work[i] << " ";
cout << endl;
}
void ShowAllOfData() { //此函数实为信息展示函数
this->Show_Table_Data();
this->Show_Resource_Can_Be_Used();
this->ShowWorkData();
this->ShowFinish_Data();
}
void Safety_Detected(bool flag, string Process_ND) { //重点:安全检验函数
if (flag == false)
return;
int i, Present_Process_ID, Start_Process;
bool SrcC_tBR = false, flag0 = false;
int Count;
Start_Process = 0;
vector<int> tem_vec = Available; //保存初始状态
deque<string>path;
for (i = 0; i < Finish.size(); i++) {
if (ProcessTable[i].Process_ND == Process_ND)
{
Present_Process_ID = i; //知道处理的是第几个进程
}
}
vector<int>tem_Need = ProcessTable[Present_Process_ID].Need; //可能恢复need
if (Finish[Present_Process_ID] == 1) //进程已经完成,无法继续申请资源
{
cout << "该进程已完成,无法申请资源!" << endl;
return;
}
for (i = 0; i < Available.size(); i++) { //判断可用资源是否满足申请的资源数
if (ProcessTable[Present_Process_ID].Request[i] > Available[i])
flag0 = true;
}
if (flag0) {
Safe_Flag = false;
cout << "申请资源数超出可用资源!" << endl;
return;
}
for (i = 0; i < Available.size(); i++) { //可以分配,于此分配,并进行相关参数的改变
Available[i] -= ProcessTable[Present_Process_ID].Request[i];
Work[i] -= ProcessTable[Present_Process_ID].Request[i];
ProcessTable[Present_Process_ID].Allocation[i] += ProcessTable[Present_Process_ID].Request[i];
ProcessTable[Present_Process_ID].Need[i] -= ProcessTable[Present_Process_ID].Request[i];
if (ProcessTable[Present_Process_ID].Allocation[i] < ProcessTable[Present_Process_ID].Max_Need[i]) //判断分配资源后,该进程能否释放所有资源
SrcC_tBR = true;
}
cout << endl << "开始安全性检验!" << endl << endl; //准备进入安全序列函数!
if (SrcC_tBR) { //该进程无法释放所有资源
Count = 0;
int Finished_Num = GetFinishedProcessNum(); //方便后序进程申请资源的操作.可以实现 P1申请资源:P1->P2->P3 ,P2申请资源: P2->P3的类似操作
SearchSafetyList_Condition_1(path, Count, Present_Process_ID, Finished_Num); //使用获取安全序列_1函数
}
else { //该进程可以释放所有资源
Count = 0;
string stack_low = ProcessTable[Present_Process_ID].Process_ND; //获取此时进程名称,要求输出从该进程开始的安全序列.如:P1释放资源,输出P1->P2->P3,P1->P3->P2
path.push_back(ProcessTable[Present_Process_ID].Process_ND);
for (i = 0; i < Work.size(); i++) {
Work[i] += ProcessTable[Present_Process_ID].Allocation[i];
Available[i] += ProcessTable[Present_Process_ID].Allocation[i];
}
Finish[Present_Process_ID] = true;
int Finished_Num = GetFinishedProcessNum();
SearchSafetyList_Condition_2(path, Count, Present_Process_ID, Finished_Num, stack_low); //使用获取安全序列_2函数
}
if (Count == 0) //没有安全序列
Safe_Flag = 0;
else
Safe_Flag = 1;
if (Safe_Flag == 0) { //分配资源后没有安全序列,恢复初始状态
Available = tem_vec;
Work = tem_vec;
ProcessTable[Present_Process_ID].Need = tem_Need;
for (i = 0; i < Available.size(); i++)
{
ProcessTable[Present_Process_ID].Allocation[i] = ProcessTable[Present_Process_ID].Max_Need[i] - tem_Need[i];
}
}
for (i = 0; i < Work.size(); i++) {
ProcessTable[Present_Process_ID].Request[i] = 0; //将该进程的Request清零,为下一次申请做准备
}
Bank(); //表明是否可以分配
this->ShowAllOfData(); //输出一下所有信息
}
bool Allow_Allocate(int Present_Process) { //方便回溯求解,相当于约束函数,判断某一进程是否满足被分配资源
for (int j = 0; j < Available.size(); j++)
if (ProcessTable[Present_Process].Need[j] > Available[j] || Finish[Present_Process] == true)
return false;
return true;
}
int GetFinishedProcessNum() { //获取当前所有完成的进程数,方便完成P1->P2->P3->P4-
int tem = 0;
for (int i = 0; i < Finish.size(); i++) {
if (Finish[i] == 1)
tem += 1;
}
return tem; //tem即为当前完成的进程数
}
void SearchSafetyList_Condition_1(deque<string>path, int & Count, int Present_Process, int Finished_Num) { //情况1:当分配资源后,进程无法释放所有资源
if (path.size() == this->Finish.size() - Finished_Num) { //可以使得不输出Finish位已经是1的进程(此处不减一!)
PrintWholePath(path);
Count++;
return;
}
int i;
for (Present_Process = 0; Present_Process < this->Finish.size(); Present_Process++) //为进程j试探分配资源(回溯法输出所有安全路径)
{
if (Allow_Allocate(Present_Process)) {
for (i = 0; i < Work.size(); i++) {
Work[i] += ProcessTable[Present_Process].Allocation[i];
Available[i] += ProcessTable[Present_Process].Allocation[i];
}
Finish[Present_Process] = true;
path.push_back(ProcessTable[Present_Process].Process_ND);
SearchSafetyList_Condition_1(path, Count, Present_Process + 1, Finished_Num);
path.pop_back();
Finish[Present_Process] = false;
for (i = 0; i < Work.size(); i++) {
Work[i] -= ProcessTable[Present_Process].Allocation[i];
Available[i] -= ProcessTable[Present_Process].Allocation[i];
}
}
}
}
void SearchSafetyList_Condition_2(deque<string>path, int & Count, int Present_Process, int Finished_Num, string stack_low) { //情况2:分配资源后,当前进程可以释放所有资源
if (path.size() == this->Finish.size() || path.size() == this->Finish.size() - Finished_Num + 1) { //仅输出以当前进程为起点的安全路径! //两次reversepath是为了判定栈底元素是否符合条件!(此处队列更好)
if (path.front() == stack_low) {
PrintWholePath(path);
Count++;
}
return;
}
int i, j;
for (j = 0; j < this->Finish.size(); j++) //为进程j试探分配资源
{
if (Allow_Allocate(j)) {
for (i = 0; i < Work.size(); i++) {
Work[i] += ProcessTable[j].Allocation[i];
Available[i] += ProcessTable[j].Allocation[i];
}
Finish[j] = true;
path.push_back(ProcessTable[j].Process_ND);
SearchSafetyList_Condition_2(path, Count, j + 1, Finished_Num, stack_low);
path.pop_back();
Finish[j] = false;
for (i = 0; i < Work.size(); i++) {
Work[i] -= ProcessTable[j].Allocation[i];
Available[i] -= ProcessTable[j].Allocation[i];
}
}
}
}
void Bank() { //银行家函数仅根据标志位进行进行判定
if (Safe_Flag) {
cout << "安全,可以分配资源" << endl << endl;
}
else
cout << "不安全,拒绝分配资源!" << endl << endl;
}
void PrintWholePath(deque<string>path) { //输出整个栈的元素(从栈底到栈顶)
deque<string>tem;
string* s;
while (!path.empty()) {
s = new string;
*s = path.back();
tem.push_back(*s);
path.pop_back();
}
while (!tem.empty()) {
s = new string;
*s = tem.back();
path.push_back(*s);
tem.pop_back();
if (!tem.empty())
cout << *s << "->";
else
cout << *s << endl << endl;
}
}
~Process_Table() {};
};
这里是大工程,搞的我头都发晕.
part3.代码(!)解
代码都给到上面了而且还是面向对象写的,这还得详解其实就难受了.主函数如下:
void main() {
FILE* stream4;
freopen_s(&stream4, "D:\\码农人码农魂\\操作系统\\Input_File4.txt", "r", stdin);
int Resource_Num, Process_Num;
cin >> Resource_Num >> Process_Num;
Resource_Name resource_name;
vector<string> resource;
vector<Basic_Process_Message> bpm;
Process_Table pt;
//=============================================================================以上为需在main函数中定义的基本数据结构
resource_name.Create_Resource_Index(resource, Resource_Num);
pt.Initial_Process_Index(bpm, Process_Num, resource, Resource_Num); //初始化进程数组
pt = Process_Table(bpm, Process_Num); //至此完成初始化
freopen_s(&stream4, "CON", "r", stdin); //定向输入到控制台
pt.ShowAllOfData(); //该函数即为当前资源状况函数
//=============================================================================
//以下部分为测试部分
int Request_Process, Exit_Flag;
string Process_ND;
Exit_Flag =0;
while (!Exit_Flag) {
cout << "请依次输入申请资源的进程编号,进程名和退出标志" << endl; //在下一次循环开始后结束
cin >> Request_Process >> Process_ND >> Exit_Flag;
pt.Safety_Detected(pt.ProcessTable[Request_Process].SendRequest(), Process_ND);
}
fclose(stream4);
}
我这个的话,是用文件中数据来初始化初始进程参数的,运行结果如下:

这里资源名称,进程名称,退出标志都是自己设置的,当退出标志不为0时,程序终止.研读一下代码还是很容易理解的,然后毕竟变量名称"所见即所指".当然如果有大佬愿意帮我改进代码,我也一定会好好解释清楚滴!
后续测试很稳定,believe me嘿嘿.
本文介绍了一个使用C++实现的操作系统课程设计项目,通过面向对象编程实现了资源类、单条进程类和进程表类,用以模拟资源分配和检查安全序列。代码利用vector替代数组,简化了数据结构。程序能处理异常输入,并提供了资源申请、安全检验等功能。在资源不足时,通过安全序列检测判断是否可以分配资源。
2364





