一、 实验目的
模拟实现银行家算法,用银行家算法实现资源分配和安全性检查。通过本次实验,使学生加深对死锁概念的理解和掌握,并培养学生对操作系统课程的兴趣与高级语言设计的能力。二、 实验内容 1、要求
设计五个进程{P0···P4}共享三类资源{A,B,C}的系统,每一种资源数量为10,5,7。进程可动态的申请和释放资源,系统按各进程的申请动态地分配资源,在T0时刻的资源分配情况如下表:
Name Max Allocation Need Available
P0 7,5,3 0,1,0 7,4,3 3,3,2
P1 3,2,2 2,0,0 1,2,2
P2 9,0,2 3,0,2 6,0,0
P3 2,2,2 2,1,1 0,1,1
P4 4,3,3 0,0,2 4,3,1
(1) 银行家算法的数据结构
•Resource:一个长度为m向量,表示系统拥有的资源数目。
•Available:一个长度为m向量,表示每类资源的可用数目。
•Max:一个m×n矩阵,定义每个进程的最大资源需求数。
•Allocation:一个m×n矩阵,定义当前分配给每个进程每类资源的数目。
•Need:一个m×n矩阵,表示每个进程还需多少资源。
(2) 实现银行家算法 设:Requesti是进程Pi的请求向量。
当Pi发出资源请求后,系统按如下步骤进行检查:
•如果Request[j] Need[i][j] 则go to 2,否则认为出错。
•如果Request[j] < Available[i][j] 则go to 3,否则表示无足够资源, Pi等待。
•系统进行试探分配,并求该相应数据结构数据
Available:= Available- Requesti
Allocationi:= Allocationi+ Requesti
Needi:= Needi-Requesti
•系统执行安全性算法:安全,把资源分配给Pi,否则, Pi等待。
(3) 实现安全性算法
•设Work 和 Finish是长度分别为m,n的向量
初试值Work =Available ,Finishi = False(所有)
•从进程集合中找到一个能满足下列条件的进程
a. Finishi= False
b. Needi Work 如找到go to 3 否则 go to 4
•当进程Pi 获得资源后,顺利执行,直至完成,并释放分配给它的资源。
Work = Work+ Allocationi
Finishi:= True go to 2
•如果所有进程的Finishi= True 则表示系统安全,否则为不安全。
方案一(不利用goto语句):
//判断系统的安全性
int judSystemSecurity()
{
int i;
//更新系统可利用资源量
for (i = 0; i < resourseType; i++)
{
work[i] = available[i];
}
int allFinish = 0;
//把未完成进程置为0
for (i = 0; i < customerNumber; i++)
{
//判断当前进程是否已经完成并且可以回收资源
//如果已经全部完成
if (isFinish(i))
{
Finish[i] = 1;
allFinish++;
}
else
{
Finish[i] = 0;
}
}
int r = 0;//表示当前要判断是否要进行预分配的进程的下标
int safeIndex = 0;//安全序列的下标
int temp = 0;//临时变量
int pNum = 0;//保存临时变量的个数
//预分配开始,当进程没有全部完成时,一直执行循环
while (allFinish != customerNumber)
{
num = 0;
//判断是否可以预分配
for (i = 0; i < resourseType; i++)
{
if (need[r][i] <= work[i] && Finish[r] == 0)//判断是否可以预分配
{
num++;
}
}
//可以预分配
if (num == resourseType)
{
//输出进程Pr的各项信息
SafeInfo(work, r);
//回收资源
for (i = 0; i < resourseType; i++)
{
work[i] = work[i] + allocation[r][i];
}
//完成的进程数增加
allFinish++;
//保存安全序列
safeSeries[safeIndex] = r;
safeIndex++;
//当前进程安全
Finish[r] = 1;
}
r++;//该式必须在此处
if (r >= customerNumber)
{
r = r % customerNumber;
if (temp == allFinish)//temp记录的是上一次循环分配后所有的进程完成数,将上一次进程数跟这次预分配后的进程数
{ //进行对比,如果相等,则是不安全的情况,直接break;否则是安全的情况,继续执行
break;
}
temp = allFinish;//更新完成的进程数
}
pNum = allFinish;//保存安全序列的个数
}
//判断系统是否安全
for (i = 0; i < customerNumber; i++)
{
if (Finish[i] == 0)
{
return 0;
}
}
//打印安全序列
printf("\n安全序列为:");
for (i = 0; i < customerNumber; i++)
{
if (isFinish(i))
{
pNum--;
}
}
for (i = 0; i < pNum; i++)
{
printf("%d ", safeSeries[i]);
}
return 1;
}
方案二(利用goto语句):
//方案二,利用goto语句
int judSystemSecurity_1()
{
int i, j;
for (i = 0; i < resourseType; i++)
{
work[i] = available[i];
}
for (i = 0; i < customerNumber; i++)
{
if (isFinish(i))
{
Finish[i] = 1;
}
else
{
Finish[i] = 0;
}
}
int safeIndex = 0;
NEXT:
for (i = 0; i < customerNumber; i++)
{
if (Finish[i] == 0)
{
for (j = 0; j < resourseType; j++)
{
if (need[i][j] > work[j])
{
break;
}
}
//已完全执行
if (j == resourseType)
{
Finish[i] = 1;
SafeInfo(work, i);
safeSeries[safeIndex++] = i;
//回收资源
for (j = 0; j < resourseType; j++)
{
work[j] += allocation[i][j];
}
goto NEXT;
}
}
}
int pNum = 0;
for (i = 0; i < customerNumber; i++)
{
if (Finish[i] == 0)
{
return 0;
}
else
{
pNum++;
}
}
//打印安全序列
printf("\n安全序列为:");
for (i = 0; i < customerNumber; i++)
{
if (isFinish(i))//统计没完全执行的进程数
{
pNum--;
}
}
for (i = 0; i < pNum; i++)
{
printf("%d ", safeSeries[i]);
}
return 1;
}
//判断进程资源请求的安全性
void judRequestSecurity()
{
//输入预分配的资源编号和各类资源量
int curProcess;
printf("请输入预分配资源的进程的编号:");
scanf("%d", &curProcess);
getchar();
int i;
for (i = 0; i < resourseType; i++)
{
printf("请输入给 P%d 预分配的第 %d 类资源量:", curProcess, i + 1);
scanf("%d", &request[i]);
getchar();
}
//作为安全性的判断变量
num = 0;
//进行判断预分配是否合理
for (i = 0; i < resourseType; i++)
{
if (request[i] > need[curProcess][i])
{
printf("\n分配错误!请求分配资源量大于所需要的资源量!\n");
printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
return;
}
else if (request[i] > available[i])
{
printf("\n分配错误!请求分配资源量大于可利用资源量!\n");
printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
return;
}
else
{
num++;
}
}
//分配合理,则试探性地分配
if (num == resourseType)
{
num = 0;
for (i = 0; i < resourseType; i++)
{
available[i] -= request[i];
allocation[curProcess][i] += request[i];
need[curProcess][i] -= request[i];
if (need[curProcess][i] == 0)
{
num++;
}
}
//分配合理并且此次分配后该进程执行结束,回收资源
if (num == resourseType)
{
for (i = 0; i < resourseType; i++)
{
available[i] += allocation[curProcess][i];
}
printf("\n进程 P%d 执行完毕,所占用资源全部释放!\n", curProcess);
}
else
{
printf("\n进程 P%d 未执行完毕,等待\n", curProcess);
}
}
//检查分配后系统是否安全,如果不安全,则收回分配的资源
printf("\n------------------------------------------------------------------------------------\n");
printf("当前系统各类资源剩余量:");
for (int i = 0; i < resourseType; i++)
{
printf("%d ", available[i]);
}
printf("\n\n当前系统进程状况:\n");
printf(" Name\t Work\t Need\tAllocation\tWork+Allocation\t Finish\n");
if (!judSystemSecurity_1())
{
for (i = 0; i < resourseType; i++)
{
available[i] += request[i];
allocation[curProcess][i] -= request[i];
need[curProcess][i] += request[i];
}
printf("\n\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY", curProcess);
}
else
{
printf("\n\nRESOURCE SECURITY!!!\n\nCUSTOMER P%d CAN OBTAIN RESOURCES IMMEDIATELY", curProcess);
}
printf("\n------------------------------------------------------------------------------------\n");
return;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
//系统中每种资源的可利用资源数
int available[100] = { 0 };
//进程的最大需求资源数
int max[100][100] = { 0 };
//系统刚开始每个进程已占用资源数
int allocation[100][100] = { 0 };
//每个进程还需要的资源数
int need[100][100] = { 0 };
//判断每个进程是否安全
int Finish[100] = { 0 };
//安全序列号
int safeSeries[100];
//进程请求资源量
int request[100];
//资源计数变量,便于判断安全性
int num;
//系统当前可分配资源量
int work[1000];
//资源种类数和进程数
int resourseType, customerNumber;
//作为是否输入数据的判断变量
int flag = 0;
//函数声明
int isFinish(int row);
void SafeInfo(int* work, int index);
int judSystemSecurity();
int judSystemSecurity_1();
void judRequestSecurity();
void showMenu();
void keyDown();
void InitStastic();
//函数定义
int isFinish(int row)
{
int j;
for (j = 0; j < resourseType; j++)
{
if (need[row][j] != 0)
{
return 0;
}
}
return 1;
}
//进程资源输出
void SafeInfo(int* work, int index)
{
int j;
printf(" P%d\t", index);
for (j = 0; j < resourseType; j++)
{
printf("%d ", work[j]);
}
printf("\t ");
for (j = 0; j < resourseType; j++)
{
printf("%d ", need[index][j]);
}
printf("\t ");
for (j = 0; j < resourseType; j++)
{
printf("%d ", allocation[index][j]);
}
printf("\t ");
for (j = 0; j < resourseType; j++)
{
printf("%d ", allocation[index][j] + work[j]);
}
printf("\t T");
printf("\n");
return;
}
//方案二,利用goto语句
int judSystemSecurity_1()
{
int i, j;
for (i = 0; i < resourseType; i++)
{
work[i] = available[i];
}
for (i = 0; i < customerNumber; i++)
{
if (isFinish(i))
{
Finish[i] = 1;
}
else
{
Finish[i] = 0;
}
}
int safeIndex = 0;
NEXT:
for (i = 0; i < customerNumber; i++)
{
if (Finish[i] == 0)
{
for (j = 0; j < resourseType; j++)
{
if (need[i][j] > work[j])
{
break;
}
}
//已完全执行
if (j == resourseType)
{
Finish[i] = 1;
SafeInfo(work, i);
safeSeries[safeIndex++] = i;
//回收资源
for (j = 0; j < resourseType; j++)
{
work[j] += allocation[i][j];
}
goto NEXT;
}
}
}
int pNum = 0;
for (i = 0; i < customerNumber; i++)
{
if (Finish[i] == 0)
{
return 0;
}
else
{
pNum++;
}
}
//打印安全序列
printf("\n安全序列为:");
for (i = 0; i < customerNumber; i++)
{
if (isFinish(i))//统计没完全执行的进程数
{
pNum--;
}
}
for (i = 0; i < pNum; i++)
{
printf("%d ", safeSeries[i]);
}
return 1;
}
//判断系统的安全性
int judSystemSecurity()
{
int i;
//更新系统可利用资源量
for (i = 0; i < resourseType; i++)
{
work[i] = available[i];
}
int allFinish = 0;
//把未完成进程置为0
for (i = 0; i < customerNumber; i++)
{
//判断当前进程是否已经完成并且可以回收资源
//如果已经全部完成
if (isFinish(i))
{
Finish[i] = 1;
allFinish++;
}
else
{
Finish[i] = 0;
}
}
int r = 0;//表示当前要判断是否要进行预分配的进程的下标
int safeIndex = 0;//安全序列的下标
int temp = 0;//临时变量
int pNum = 0;//保存临时变量的个数
//预分配开始,当进程没有全部完成时,一直执行循环
while (allFinish != customerNumber)
{
num = 0;
//判断是否可以预分配
for (i = 0; i < resourseType; i++)
{
if (need[r][i] <= work[i] && Finish[r] == 0)//判断是否可以预分配
{
num++;
}
}
//可以预分配
if (num == resourseType)
{
//输出进程Pr的各项信息
SafeInfo(work, r);
//回收资源
for (i = 0; i < resourseType; i++)
{
work[i] = work[i] + allocation[r][i];
}
//完成的进程数增加
allFinish++;
//保存安全序列
safeSeries[safeIndex] = r;
safeIndex++;
//当前进程安全
Finish[r] = 1;
}
r++;//该式必须在此处
if (r >= customerNumber)
{
r = r % customerNumber;
if (temp == allFinish)//temp记录的是上一次循环分配后所有的进程完成数,将上一次进程数跟这次预分配后的进程数
{ //进行对比,如果相等,则是不安全的情况,直接break;否则是安全的情况,继续执行
break;
}
temp = allFinish;//更新完成的进程数
}
pNum = allFinish;//保存安全序列的个数
}
//判断系统是否安全
for (i = 0; i < customerNumber; i++)
{
if (Finish[i] == 0)
{
return 0;
}
}
//打印安全序列
printf("\n安全序列为:");
for (i = 0; i < customerNumber; i++)
{
if (isFinish(i))
{
pNum--;
}
}
for (i = 0; i < pNum; i++)
{
printf("%d ", safeSeries[i]);
}
return 1;
}
//判断进程资源请求的安全性
void judRequestSecurity()
{
//输入预分配的资源编号和各类资源量
int curProcess;
printf("请输入预分配资源的进程的编号:");
scanf("%d", &curProcess);
getchar();
int i;
for (i = 0; i < resourseType; i++)
{
printf("请输入给 P%d 预分配的第 %d 类资源量:", curProcess, i + 1);
scanf("%d", &request[i]);
getchar();
}
//作为安全性的判断变量
num = 0;
//进行判断预分配是否合理
for (i = 0; i < resourseType; i++)
{
if (request[i] > need[curProcess][i])
{
printf("\n分配错误!请求分配资源量大于所需要的资源量!\n");
printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
return;
}
else if (request[i] > available[i])
{
printf("\n分配错误!请求分配资源量大于可利用资源量!\n");
printf("\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY\n\n", curProcess);
return;
}
else
{
num++;
}
}
//分配合理,则试探性地分配
if (num == resourseType)
{
num = 0;
for (i = 0; i < resourseType; i++)
{
available[i] -= request[i];
allocation[curProcess][i] += request[i];
need[curProcess][i] -= request[i];
if (need[curProcess][i] == 0)
{
num++;
}
}
//分配合理并且此次分配后该进程执行结束,回收资源
if (num == resourseType)
{
for (i = 0; i < resourseType; i++)
{
available[i] += allocation[curProcess][i];
}
printf("\n进程 P%d 执行完毕,所占用资源全部释放!\n", curProcess);
}
else
{
printf("\n进程 P%d 未执行完毕,等待\n", curProcess);
}
}
//检查分配后系统是否安全,如果不安全,则收回分配的资源
printf("\n------------------------------------------------------------------------------------\n");
printf("当前系统各类资源剩余量:");
for (int i = 0; i < resourseType; i++)
{
printf("%d ", available[i]);
}
printf("\n\n当前系统进程状况:\n");
printf(" Name\t Work\t Need\tAllocation\tWork+Allocation\t Finish\n");
if (!judSystemSecurity_1())
{
for (i = 0; i < resourseType; i++)
{
available[i] += request[i];
allocation[curProcess][i] -= request[i];
need[curProcess][i] += request[i];
}
printf("\n\nRESOURCE INSECURITY!!!\n\nCUSTOMER P%d CAN NOT OBTAIN RESOURCES IMMEDIATELY", curProcess);
}
else
{
printf("\n\nRESOURCE SECURITY!!!\n\nCUSTOMER P%d CAN OBTAIN RESOURCES IMMEDIATELY", curProcess);
}
printf("\n------------------------------------------------------------------------------------\n");
return;
}
//菜单
void showMenu()
{
printf(" ====================菜单栏=====================\n");
printf("\n\t 0、input datas\n");
printf("\n\t 1、judge the system security\n");
printf("\n\t 2、judge the request security\n");
printf("\n\t 3、quit\n");
printf("\n ===============================================\n");
return;
}
//检测用户按键输入
void keyDown()
{
NEXT:
;
int hit;
printf("请输入你的选择:");
scanf("%d", &hit);
switch (hit)
{
case 0:
NEXT_1:
flag = 1;
InitStastic();
break;
case 1://判断系统安全性
if (flag)
{
printf("\n------------------------------------------------------------------------------------\n");
printf("当前系统各类资源剩余量:");
for (int i = 0; i < resourseType; i++)
{
printf("%d ", available[i]);
}
printf("\n\n当前系统进程状况:\n");
printf(" Name\t Work\t Need\tAllocation\tWork+Allocation\t Finish\n");
if (judSystemSecurity_1())
{
printf("\n\nSYSTEM SECURITY!!!");
}
else
{
printf("\n\nSYSTEM INSUFFICIENT!!!");
}
printf("\n------------------------------------------------------------------------------------\n");
}
else
{
printf("还未输入数据!请先输入相关数据\n");
goto NEXT_1;
}
break;
case 2://判断进程请求的安全性
if (flag)
{
judRequestSecurity();
}
else
{
printf("还未输入数据!请先输入相关数据\n");
goto NEXT_1;
}
break;
case 3://退出
printf("\n正常退出!\n");
exit(-1);
default:
printf("\n输入错误,请重新输入指令!\n");
system("pause");
system("cls");
showMenu();
goto NEXT;
break;
}
}
void InitStastic()
{
printf("Input the type of resource and number of customer:\n");
scanf("%d%d", &resourseType, &customerNumber);
getchar();
printf("\nInput the amount of resource (maximum , allocated) of each customer:\n");
int i, j;
for (i = 0; i < customerNumber; i++)
{
for (j = 0; j < resourseType; j++)
{
printf("请输入进程 P%d 的第 %d 类资源的最大需求量:", i, j + 1);
scanf("%d", &max[i][j]);
getchar();
}
printf("\n\n");
for (j = 0; j < resourseType; j++)
{
printf("请输入进程 P%d 的第 %d 类资源的已占用资源量:", i, j + 1);
scanf("%d", &allocation[i][j]);
getchar();
}
printf("\n\n");
for (j = 0; j < resourseType; j++)
{
need[i][j] = max[i][j] - allocation[i][j];
}
}
printf("\nInput the amout of resources(available):\n");
for (i = 0; i < resourseType; i++)
{
printf("请输入第%d类资源的可利用量:", i + 1);
scanf("%d", &available[i]);
getchar();
}
printf("\n数据录入成功!\n");
return;
}
int main(int argc, char* argv[])
{
while (1)
{
showMenu();
keyDown();
system("pause");
system("cls");
}
return 0;
}
有任何问题可以留言交流,我一定及时回复