老生常谈的算法,思想很简单,但是实现起来,想跟踪每一步的结果,有点繁琐,详细介绍一下算法的实现过程,也防止自己以后遗忘。编程环境为windows,VC6.0,最古老也是最经典的环境吧。
首先说明几个矩阵,如下所示
#define P 5 //5个任务 #define R 3 //3种资源 int Max[P][R]; //最大需求资源 int Allocation[P][R]; //已分配资源 int Available[R]; //当前可用资源 int Need[P][R]; //任务还需要的资源
其中Max和Allocation是从文件读取,Need是Max-Allocation计算结果,Available是手动输入,初始状态,Max和Allocation的值分别如下:
//max.txt 7 5 3 3 2 2 9 0 2 2 2 2 4 3 3 //allocation.txt 0 1 0 2 0 0 3 0 2 2 1 1 0 0 2
文件读取函数input如下
//从文本中读取数据函数,需要头文件#include <fstream> void input(FILE* fp, int ptr[P][R]) { int i,j; for(i=0; i<P; i++) { for(j=0; j<R; j++) { fscanf(fp, "%d", &ptr[i][j]); } fscanf(fp, "\n"); } fclose(fp); }
计算Need矩阵函数
//计算Need矩阵并输出 void computeNeed(int need[P][R], int ptr1[P][R], int ptr2[P][R]) { int i,j; for(i=0; i<P; i++) { for(j=0; j<R; j++) { need[i][j] = ptr1[i][j] - ptr2[i][j]; } } cout<<"当前"<<P<<"个任务还需要的资源为:"<<endl; for(i=0; i<P; i++) { cout<<"P("<<i<<"):"<<" "; for(j=0; j<R; j++) { cout<<need[i][j]<<" "; } cout<<endl; } }
主函数中对于的调用方式为:
#define maxDataPath "E:\\VC6.0_test_program\\BankerAlgorithm\\max.txt" #define allocationDataPath "E:\\VC6.0_test_program\\BankerAlgorithm\\allocation.txt" FILE *fpMax = fopen(maxDataPath, "r"); FILE *fpAllocation = fopen(allocationDataPath, "r"); input(fpMax, Max); cout<<"当前"<<P<<"个任务需要的最大资源为:"<<endl; output(fpMax, Max); input(fpAllocation, Allocation); cout<<"当前"<<P<<"个任务已分配的资源为:"<<endl; output(fpAllocation, Allocation); computeNeed(Need, Max, Allocation); //计算Need矩阵并输出
安全性检查函数,其中secure[P][R]矩阵用来保存Available和Need的差值,若secure[i][j] < 0,则当前第j类可用资源小于第i个任务第j类需求资源,计数器+1,一次循环下来,当计数器的值仍然为0时(每个循环开始时计数器会清零),才表示第i个任务满足资源分配要求,返回其下标,否则,返回-1。如下所示
//安全性检查,比较Need和Available,如果有任务处于安全状态,则返回其下标,否则返回-1 int securityCheck(int Allocation[P][R], int Need[P][R], int Available[R]) { int i,j; int secure[P][R]; int count[P]; for(i=0; i<P; i++) { int c = 0; //计数器清零 cout<<"secure["<<i<<"][]的值为:"; for(j=0; j<R; j++) { secure[i][j] = Available[j] - Need[i][j]; cout<<secure[i][j]<<" "; if(secure[i][j] < 0) ++c; } count[i] = c; //count[i]!=0表示第i个任务不满足资源分配要求 cout<<"count["<<i<<"]的值是:"<<count[i]<<endl; } for(i=0; i<P; i++) { if(count[i] == 0) { return i; } } return -1; }修改矩阵函数set,当存在安全序列时,每执行完一个任务,修改当前可用资源矩阵Available的值,并且将该任务的Need设置为1000(更大的数也可以,只要让它足够大,大到大于Available就可以),表示执行完该任务。
//当存在安全序列时,每执行完一个任务,修改当前可用资源矩阵Available的值,并且将该任务的Need设置为1000 void set(int sequence, int Need[P][R], int Allocation[P][R], int Available[R]) { int j; cout<<"此时Available为:"; for(j=0; j<R; j++) { Available[j] = Available[j] + Allocation[sequence][j]; Need[sequence][j] = 1000; cout<<Available[j]<<" "; } cout<<endl; cout<<endl; }
主函数对应的调用如下:
int sequence;//sequence是安全序列的任务下标 for(i=0; i<P; i++) { sequence = securityCheck(Allocation, Need, Available); cout<<"sequence的值为"<<sequence<<endl; if(sequence != -1) { cout<<"执行任务P("<<sequence<<")"<<endl; set(sequence, Need, Allocation, Available); } else { cout<<"错误,资源不够执行任务!"<<endl; break; } }
考虑到当前状态会有任务请求资源,故设置了一个请求检查函数,检测任务请求的资源是否合理合法,其中requestSeq是手动输入的请求任务下标,Request[R]也是手动输入的请求资源,如果请求资源既不大于当前该任务的需求资源,也不大于当前可用资源,则说明对该类资源的请求合法,index+1,所以当index==3为真时,表示该任务请求的资源合法,返回请求任务的下标,否则当循环结束时返回-1
//请求检查,检测任务请求的资源是否合理合法 int requestCheck(int requestSeq, int Request[R], int Need[P][R], int Available[R]) { int i=0; int index = 0; while(i<R) { if(Request[i] <= Need[requestSeq][i]) //判断请求资源是否不大于当前该任务的需求资源 { if(Request[i] <= Available[i]) //判断请求资源是否不大于当前可用资源 { ++index; //index=3表示请求资源合理 ++i; } else{ cout<<"请求的第"<<i<<"种资源可用资源不足!"<<endl; ++i; //ntinue; } }else{ cout<<"请求的第"<<i<<"种资源超过任务P("<<requestSeq<<")的需求,请重新输入!"<<endl; ++i; } } cout<<"index的值为:"<<index<<endl; if(index == 3) { return requestSeq; //请求资源合法,返回请求任务的下标 } return -1; }
在请求完资源且检查过请求合法,那么重新分配当前资源,修改Allocation、Need、Available矩阵
//请求资源后,重新分配当前资源,修改Allocation、Need、Available矩阵 void afterReq(int requestSeq, int Request[R], int Allocation[P][R], int Need[P][R], int Available[R]) { int i; for(i=0; i<R; i++) { Allocation[requestSeq][i] = Allocation[requestSeq][i] + Request[i]; Need[requestSeq][i] = Need[requestSeq][i] - Request[i]; Available[i] = Available[i] - Request[i]; } }
完整代码如下:
#include <iostream.h> #include <stdio.h> #include <fstream> #define maxDataPath "E:\\VC6.0_test_program\\BankerAlgorithm\\max.txt" //文件路径 #define allocationDataPath "E:\\VC6.0_test_program\\BankerAlgorithm\\allocation.txt" //#define availableDataPath "E:\\C++\\BankerAlgorithm\\available.txt" #define P 5 //5个任务 #define R 3 //3种资源 //从文本中读取数据函数 void input(FILE* fp, int ptr[P][R]) { int i,j; for(i=0; i<P; i++) { for(j=0; j<R; j++) { fscanf(fp, "%d", &ptr[i][j]); } fscanf(fp, "\n"); } fclose(fp); } //输出数据函数 void output(FILE* fp, int ptr[P][R]) { int i,j; for(i=0; i<P; i++) { cout<<"P("<<i<<"):"<<" "; for(j=0; j<R; j++) { cout<<ptr[i][j]<<" "; } cout<<endl; } } //计算Need矩阵并输出 void computeNeed(int need[P][R], int ptr1[P][R], int ptr2[P][R]) { int i,j; for(i=0; i<P; i++) { for(j=0; j<R; j++) { need[i][j] = ptr1[i][j] - ptr2[i][j]; } } cout<<"当前"<<P<<"个任务还需要的资源为:"<<endl; for(i=0; i<P; i++) { cout<<"P("<<i<<"):"<<" "; for(j=0; j<R; j++) { cout<<need[i][j]<<" "; } cout<<endl; } } //安全性检查,比较Need和Available,如果有任务处于安全状态,则返回其下标,否则返回-1 int securityCheck(int Allocation[P][R], int Need[P][R], int Available[R]) { int i,j; int secure[P][R]; int count[P]; for(i=0; i<P; i++) { int c = 0; //计数器清零 cout<<"secure["<<i<<"][]的值为:"; for(j=0; j<R; j++) { secure[i][j] = Available[j] - Need[i][j]; cout<<secure[i][j]<<" "; if(secure[i][j] < 0) ++c; } count[i] = c; //count[i]!=0表示第i个任务不满足资源分配要求 cout<<"count["<<i<<"]的值是:"<<count[i]<<endl; } for(i=0; i<P; i++) { if(count[i] == 0) { return i; } } return -1; } //当存在安全序列时,每执行完一个任务,修改当前可用资源矩阵Available的值,并且将该任务的Need设置为1000 void set(int sequence, int Need[P][R], int Allocation[P][R], int Available[R]) { int j; cout<<"此时Available为:"; for(j=0; j<R; j++) { Available[j] = Available[j] + Allocation[sequence][j]; Need[sequence][j] = 1000; cout<<Available[j]<<" "; } cout<<endl; cout<<endl; } //请求检查,检测任务请求的资源是否合理合法 int requestCheck(int requestSeq, int Request[R], int Need[P][R], int Available[R]) { int i=0; int index = 0; while(i<R) { if(Request[i] <= Need[requestSeq][i]) //判断请求资源是否不大于当前该任务的需求资源 { if(Request[i] <= Available[i]) //判断请求资源是否不大于当前可用资源 { ++index; //index=3表示请求资源合理 ++i; } else{ cout<<"请求的第"<<i<<"种资源可用资源不足!"<<endl; ++i; //ntinue; } }else{ cout<<"请求的第"<<i<<"种资源超过任务P("<<requestSeq<<")的需求,请重新输入!"<<endl; ++i; } } cout<<"index的值为:"<<index<<endl; if(index == 3) { return requestSeq; //请求资源合法,返回请求任务的下标 } return -1; } //请求资源后,重新分配当前资源,修改Allocation、Need、Available矩阵 void afterReq(int requestSeq, int Request[R], int Allocation[P][R], int Need[P][R], int Available[R]) { int i; for(i=0; i<R; i++) { Allocation[requestSeq][i] = Allocation[requestSeq][i] + Request[i]; Need[requestSeq][i] = Need[requestSeq][i] - Request[i]; Available[i] = Available[i] - Request[i]; } } void main(){ int Max[P][R]; //最大需求资源 int Allocation[P][R]; //已分配资源 int Available[R]; //当前可用资源 int Need[P][R]; //任务还需要的资源 int Request[R]; int i; int sequence,requestSeq; //sequence是安全序列的任务下标,requestSeq是请求资源的任务下标 char isRequest; bool isLegal = false; FILE *fpMax = fopen(maxDataPath, "r"); FILE *fpAllocation = fopen(allocationDataPath, "r"); input(fpMax, Max); cout<<"当前"<<P<<"个任务需要的最大资源为:"<<endl; output(fpMax, Max); input(fpAllocation, Allocation); cout<<"当前"<<P<<"个任务已分配的资源为:"<<endl; output(fpAllocation, Allocation); computeNeed(Need, Max, Allocation); //计算Need矩阵并输出 cout<<"输入当前可分配资源"<<endl; for(i=0; i<R; i++) { cin>>Available[i]; } cout<<"是否有任务发出资源请求?输入y(yes)或者n(no):"; cin>>isRequest; while(isRequest == 'y') { cout<<"第几个任务发出的资源请求?输入0到"<<P-1<<":"; cin>>requestSeq; if(requestSeq < 0 || requestSeq >= P) { cout<<"错误!输入正确的任务编号!"<<endl; } while(requestSeq >= 0 && requestSeq < P) { cout<<"P("<<requestSeq<<")请求的资源为:"; for(i=0; i<R; i++) { cin>>Request[i]; } requestSeq = requestCheck(requestSeq, Request, Need, Available); if(requestSeq != -1) { cout<<"请求资源合法"<<endl; isLegal = true; afterReq(requestSeq, Request, Allocation, Need, Available); break; } } if(isLegal) break; } cout<<"准备计算sequence"<<endl; for(i=0; i<P; i++) { sequence = securityCheck(Allocation, Need, Available); cout<<"sequence的值为"<<sequence<<endl; if(sequence != -1) { cout<<"执行任务P("<<sequence<<")"<<endl; set(sequence, Need, Allocation, Available); } else { cout<<"错误,资源不够执行任务!"<<endl; break; } } }
测试结果:
输入Available之前
如果没有任务发出请求,当前存在安全序列P1、P3、P0、P2、P4,并且在每执行完一次任务的时候,实时打印出当前可用资源Available矩阵:
当有任务发出请求时,先输入是哪个任务发出的请求,输入值要经过一次判断在任务下标范围之内,如果请求资源超过其所需的Max资源,则需要重新输入,如下所示
如果请求资源没有超过其所需的Max资源,但大于当前可用资源,仍会指出哪种请求不合法以及不合法原因
如果请求合理合法,但系统分配资源的话,导致安全性检查失败,不存在安全序列,会弹出错误提示:
最后,如果请求合理合法,且存在安全序列,则给出安全序列:
虽然有点繁琐,但并不复杂,跟踪每一步结果,更容易理解算法的思想