一、 需求分析
(1)问题分析:
- 银行家算法是避免死锁的算法,它是在系统进行资源分配之前,计算此次分配后状态的安全性。若此次分配后的状态是安全状态,则将资源分配给进程,若不是安全状态则令进程等待。
(2)功能要求:
- 有录入界面,动态录入进程数、资源种类数、各类资源总数、T0时刻各进程的最大需求数、已分配数等信息;
- 有算法选择界面,能够进行安全性检测、对进程动态请求资源的银行家算法检查、退出等的功能选择,要求可以进行多进程多次的资源请求;
- 有输出界面,要求能够输出安全性检测的结果、如安全能够输出安全序列、能够输出进程请求资源后是否分配的结果,若不能分配要输出原因,如果能够分配,要输出分配后进程及资源的状态。
(3)输入的形式和输入值的范围:
- 输入的进程个数和资源种类数位整型数字;
- 输入的资源总数,各进程对各资源的最大需求以及各进程已经占有的各资源数目以矩阵形式输入,输入值也为整数。
(4)输出的形式:
- 安全序列按顺序输出,系统剩余资源,各进程对各资源的需求情况用矩阵输出。
二、 概要设计
(1)数据结构
- 数组:Resourse[max]存放资源总数,Request[max]存放申请资源数,Avaliable[max]存放系统剩余资源,SafeOrder[max]存放安全序列;
- 矩阵:MAX[max][max]进程最大资源需求矩阵,Need[max][max]进程目前资源需求矩阵, Allocation[max][max]进程已分配资源矩阵。
(2)程序模块
- void Input(int a, int b, int c[max][max]):此函数用来输入
MAX和Allocation矩阵的值; - void init():此函数用来初始化进程个数,资源总类数,各类资源总数量,MAX和Allocation矩阵并且计算所需矩阵;
- bool IsSafe():此函数用来寻找安全序列;
- void printOrder():此函数用来输出安全序列;
- bool Apply():此函数进行资源申请;
- bool banker():此函数进行资源试分配;
- void print():此函数用来输出Avaliable,Allocation ,Need;
- void judge():判断是否有进程需求为零,若有则进行资源回收;
- void Menu():菜单函数,输出界面,根据选择调用不同函数;
- int main():主函数。
(3) 各模块之间的调用关系
- 首先,在主函数main()调用菜单函数Menu(),在菜单函数中,当用户输入1.初始化数据时,调用init()函数初始化数据,在init()函数初始化矩阵时又调用Input()函数。初始化数据之后调用IsSafe()检查T0时刻的安全性,若安全则调用printOrder()输出安全序列,调用print()输出相关矩阵信息,否则重新初始化。
- 其次,输出安全序列后调用Apply()函数进行进程申请,若申请成功调用banker()试分配,试分配时继续调用IsSafe()检查安全性,安全则输出安全序列,否则撤回分配,进行重新申请。若申请失败则重新申请。
- 最后,若没有进程申请则结束,若有则继续申请。
各模块间调用的流程图如下:
三、详细设计
1.bool IsSafe()函数:
(1)功能描述:
此函数主要功能是寻找安全性序列;
定义Finish[i]数组,用来记录进程是否已分配,然后将Available[i]数组赋给Work[i]工作数组。每次从第一个进程开始查找,若进程满足Finish[i] == false即进程尚未分配,Need[i][j] <= Work[j]即需求小于可分配资源,则Work[j] += Allocation[i][j]即释放资源,再将该进程置为已分配,即Finish[i] = true。若寻找完毕后还有进程处于为分配状态即没有找到安全序列。
(2)流程图:
(3)核心代码:
bool IsSafe() {
int i, j, k = 0, count, Work[max];
bool Finish[max];
for (i = 0; i < PN; i++) {
//所有进程初始时没有分配,Finish数组为false
Finish[i] = false;
}
for (i = 0; i < RT; i++) {
Work[i] = Avaliable[i];
}
for (i = 0; i < PN; i++) {
count = 0, j = 0; //count用来记录Need数组中的所有元素是否分别小于Work中的所有元素
if (Finish[i] == false) {
//如果进程没有分配
for (j = 0; j < RT; j++) {
if (Need[i][j] <= Work[j]) {
//并且need<work
count++;//若小于则自加
}
}
}
if (count == RT) {
//count==RT代表判断完毕
for (j = 0; j < RT; j++) {
Work[j] += Allocation[i][j];
}
Finish[i] = true;
SafeOrder[k++] = i + 1;
i = -1;//每次从第一个进程开始寻找
}
}
for (i = 0; i < PN; i++) {
//如果还有进程资源没有分配成功返回False,即状态不安全
if (Finish[i] == false) {
return false;
}
}
return true;
}
2.bool Apply()函数
(1)功能描述:
先从键盘上接收选择申请资源的进程和各资源申请数量,然后进行Request[i] <= Need[choice - 1][i]和Request[i] <= Avaliable[i]的比较,若以上两个式子都满足,则返回true。
(2)流程图:
(3)核心代码:
bool Apply() {
//资源申请
int i;
printf("选择申请资源的进程: P");
scanf("%d", &choice);
printf("\n");
printf("输入各类资源申请数量\n");
for (i = 0; i < RT; i++) {
printf("R%d ", i + 1);
}
printf("\n");
for (i = 0; i < RT; i++) {
scanf("%d", &Request[i]);
}
printf("\n");
for (i = 0; i < RT; i++) {
if (Request[i] <= Need[choice - 1][i])//choice-1行的元素逐个比较
{
if (Request[i] > Avaliable[i])
{
printf("资源不足! ");
printf("\n");
return false;
}
}
else
{
printf("申请超出所需! ");
printf("\n");
return false;
}
}
return true;
}
3.bool banker()函数