©️ 文章来源:神风の九_操作系统实验-CSDN博客,原创内容,转载请注明!
一、实验内容
问题描述:
设计程序模拟预防进程死锁的银行家算法的工作过程。假设有系统中有n个进程P1, … ,Pn,有m类可分配的资源R1, … ,Rm,在T0时刻,进程Pi分配到的j类资源为Allocationij个,它还需要j类资源Need ij个,系统目前剩余j类资源Workj个,现采用银行家算法进行进程资源分配预防死锁的发生。
程序要求:
1)判断当前状态是否安全,如果安全,给出安全序列;不安全则给出理由。
2)对于下一个时刻T1,某个进程Pk会提出请求Request(R1, … ,Rm),判断分配给P k进程请求的资源之后。
3)输入:进程个数n,资源种类m,T0时刻各个进程的资源分配情况(可以运行输入,也可以在程序中设置);
4)输出:如果安全输出安全的进程序列,不安全提示信息。
二、完整代码
#include<iostream>
using namespace std;
//线程数
#define ThreadNum 5
//初始化变量
int n=5, m=3; //5行3列
int Available[ThreadNum] = {3,3,2};
int Allocation[ThreadNum][ThreadNum] = {{0,1,0}, {2,0,0}, {3,0,2},{2,1,1},{0,0,2}};
int Need[ThreadNum][ThreadNum] = {{7,4,3}, {1,2,2}, {6,0,0}, {0,1,1}, {4,3,1}};
//定义中间变量
int Max[ThreadNum][ThreadNum];
int tempAvailable[ThreadNum]; //实时状态的可分配资源
int Request[ThreadNum];
int SafeThread[ThreadNum];
bool Finished[ThreadNum];
static int isSafe;
bool compare(int* ava, int* need){ //比较数组availabled和数组Need
//如果availabled中有一个小于Need,立即输出false
for (int i = 0; i<m; i++){
if (ava[i]<need[i]){
return false;
}
}
return true;
}
bool isSafeThread(int* tempAva){
int finishThreadNum = 0;
int i;
for (i = 0; i<n; i++){
Finished[i] = false;
}
for (i = 0; i<n; i++){
for (int j = 0; j < n; j++){
if (compare(tempAva, Need[j]) && Finished[j] == false){
for (int k = 0; k<m; k++) {
tempAva[k] += Allocation[j][k];
}
Finished[j] = true;
SafeThread[finishThreadNum] = j;
finishThreadNum++;
break;
}
}
}
if (finishThreadNum == n){
isSafe = 1;
cout << "存在安全序列:";
for (int s = 0; s<n; s++) {
cout << "P" << SafeThread[s] << " ";
}
cout << endl;
return true;
} else {
isSafe = 0;
cout << "不存在安全序列" << endl;
return false;
}
}
void print(){
cout<<"线程\t Max\t\tAllocation\tNeed\t Available" << endl;
for (int i = 0; i<n; i++){
cout<<"P"<<i<<"\t";
for (int j = 0; j<m; j++){
cout << Max[i][j] << " ";
}
cout << "\t";
for (int j = 0; j<m; j++){
cout << Allocation[i][j] << " ";
}
cout << "\t\t";
for (int j = 0; j<m; j++){
cout << Need[i][j] << " ";
}
if (i == 0){
cout << " ";
for (int j = 0; j<m; j++)
cout << Available[j] << " ";
}
cout << endl;
}
}
int main(){
cout<<"预防进程死锁的银行家算法"<<endl;
for (int i = 0; i<n; i++){
for (int j = 0; j<m; j++){
Max[i][j] = Allocation[i][j] + Need[i][j];
}
}
print();
for (int i = 0; i<m; i++){
tempAvailable[i] = Available[i];
}
int flag = isSafeThread(tempAvailable);
if (flag){
int requestLoc;
while (1){
cout<<"输入请求资源的进程下标:"<<endl;
cin >> requestLoc;
cout<<"输入请求向量:"<<endl;
for (int j = 0; j<m; j++)
{
cin >> Request[j];
Available[j] -= Request[j];
Need[requestLoc][j] -= Request[j];
Allocation[requestLoc][j] += Request[j];
}
for (int i = 0; i<m; i++){
tempAvailable[i] = Available[i];
}
cout << "获得新的请求资源后状态如下" << endl;
isSafeThread(tempAvailable);
print();
if (isSafe == 0){
for (int j = 0; j<m; j++){
//不安全,恢复初始值
Available[j] += Request[j];
Need[requestLoc][j] += Request[j];
Allocation[requestLoc][j] += Request[j];
}
}
}
}
return 0;
}
三、代码解析
1、初始化输入变量,定义Allocation、Need、Available变量,并赋初始值,初始值为书上的资源分配表示例。如下:
2、定义程序中需要使用到的中间变量
3、计算Max的值,通过Allocation+Need得到
4、定义finishThreadNum为已完成的进程数量,初始化全部进程都未完成
5、对于进程未完成且可分配资源满足该进程需求,标记该进程fanish = true,释放该进程资源,同时记录已释放进程数+1.
6、判断进程序列是否安全,如果已释放进程数 == 总进程数,则安全,反之不安全。
7、某个进程发出请求向量,需要输入进程下标和请求向量,资源请求后,要改变值。
8、判断新的请求资源是否会造成线程不安全,若线程不安全,则恢复Available、Need、Allocation的初始值。
9、输出各个进程状态的函数,如果有新的请求,可能会发生动态变化。
四、结果展示
1、使用书上的输入示例,结果为线程安全,序列为P1->P3->P0->P2->P4,结果如下
2、P1发出请求向量(1,0,2),安全
3、P4发出请求向量(3,3,0),不安全
4、P0发出请求向量(0,2,0),不安全
5、P0发出请求向量(0,1,0),安全
五、总结
首先,输入进程相关信息数据,并计算Max值,然后存入数组中。再确认最初可分配资源数,开始执行进程。接下来,判断已有资源数量是否大于进程资源需求量,如果满足,则执行进程,并回收已分配的资源,修改已有资源数量,如果不满足,则跳过,开始判断下一个进程。依次确定进程执行顺序,最后判断进程是否安全,输出结果。当某个进程提出资源请求时,先判断是否有足够的资源满足请求,如果满足则修改该进程的allocation和need,同时已有资源数量相应减少。再之后和上面步骤一样开始执行进程,如果不满足,请求则失败。这一过程可以不断循环执行。