一、实验目的
用高级语言编写和调试一个银行家算法程序,并可以利用银行家算法模拟分配资源以及进行安全性检查。加深对银行家算法的理解。
二、实验环境:
硬件环境:计算机一台,局域网环境;
软件环境:Windows XP及以上版本 Professional操作系统平台,Visual C++ 6.0专业版或企业版。
三、实验指导
1. 银行家算法中的数据结构
(1) 可利用资源向量Available。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Available[j]=K,则表示系统中现有Rj类资源K个。
(2) 最大需求矩阵Max。这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。
(3) 分配矩阵Allocation。这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的数目为K。
(4) 需求矩阵Need。这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]
2. 银行家算法
设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
(1) 如果Requesti[j]≤Need[i,j],便转向步骤2;否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
(2) 如果Requesti[j]≤Available[j],便转向步骤(3);否则, 表示尚无足够资源,Pi须等待。
(3) 系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j]= Available[j]-Requesti[j];
Allocation[i,j]= Allocation[i,j]+Requesti[j];
Need[i,j]= Need[i,j]-Requesti[j];
(4) 系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则, 将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
3. 安全性算法
(1) 设置两个向量:① 工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work∶=Available; ② Finish: 它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]=false; 当有足够资源分配给进程时, 再令Finish[i]=true。
(2) 从进程集合中找到一个能满足下述条件的进程: ① Finish[i]=false; ② Need[i,j]≤Work[j]; 若找到, 执行步骤(3), 否则,执行步骤(4)。
(3) 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j]=Work[i]+Allocation[i,j];
Finish[i]=true;
go to step 2;
(4) 如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。
四、提示
可以用下面的数据作为测试数据
假定系统中有五个进程{P0, P1, P2, P3, P4}和三类资源{A, B, C},各种资源的数量分别为10、5、7,在T0时刻的资源分配情况如图2-1 所示。
图2-1 T0时刻的资源分配表
请求序列
(1)P1发出请求向量Request1(1,0,2)
(2)P4发出请求向量Request4(3,3,0)
(3)P0发出请求向量Requst0(0,2,0)
四、实验步骤(含流程图,实验过程分析等)
过程分析:
(1)进程首次申请资源:检查请求资源是否小于need && available如果系统现存资源可以满足,则按当前的申请量分配资源,否则推迟分配。
(2)进程在执行中继续申请资源的分配:若该进程已占用的资源与本次申请的资源之和不超过对资源的最大需求量,且现存资源能满足该进程尚需的最大资源量,则按当前申请量分配资源,否则推迟分配。
(3)保证至少有一个进程能得到所需的全部资源而执行到结束,如果不存在则表示进程不安全。
(4)先将finish数组全部置为false,表示目前没有进程已经完成。然后遍历全部进程,判断每个进程的need[i][j]是否为小于可用资源,如果满足,则表示当前进程已经完成,执行finish[i] = true,并记录对应下标用于输出安全序列。
流程图:
五、实验结果及分析
图表 1 初始化结果
图表 2 菜单
- P1发出请求向量Request1(1,0,2)
进程安全,进程安全序列为:P1 P3 P4 P0 P2
(2)P4发出请求向量Request4(3,3,0)
请求向量大于可用向量(2,3,0)所以请求资源过大,无法分配资源。
(3)P0发出请求向量Requst0(0,2,0)
分配资源后可用资源将不满足任一进程所需,所以进程不安全。
六、实验源代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 20 //资源个数
#define M 50 //进程数
int available[N], maxneed[N][M], allocation[N][M], need[N][M], safe[M], temp[N]; // safe——》安全序列,temp——》储存available
int n, m, safel = 0;
bool finish[M]={false};
void Init(){ //初始化
n=5;m=3;
int maxneedl[n][m]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}}; //数组定义和初始化不能分开
int allocationl[n][m]={{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}};
for (int i = 0;i < n;i++) {
for (int j = 0;j < m;j++) {
maxneed[i][j]=maxneedl[i][j];
}
for (int j = 0;j < m;j++) {
allocation[i][j]=allocationl[i][j];
}
for (int j = 0;j < m;j++) {
need[i][j] = maxneed[i][j] - allocation[i][j];
}
}
available[0]=3;
available[1]=3;
available[2]=2;
for (int i = 0;i < m;i++) { //复原
temp[i] = available[i]; //用于后续复原available的数据
}
}
bool safety() { //安全性算法
int count = n, flag = 0, t = 0; //0为真 1为假 t判断不安全跳出循环
while (count!=0) {
for (int i = 0;i < n;i++) {
for (int j = 0;j < m;j++) {
if (available[j] < need[i][j] && finish[i] != true) {
flag = 1; //可用资源不满足当前进程的需求
}
}
if (flag == 0 && finish[i] != true) { //可用资源满足当前进程的资源请求并且当前进程没有完成
for (int k = 0;k < m;k++) {
available[k] += allocation[i][k]; //将分配资源收回
finish[i] = true; //进程完成
}
safe[safel] = i; //安全序列
safel++;
count--; //进程完成数加一,全部完成则出循环返回true
t = 1; //此次循环存在满足资源分配进程
}
flag = 0; //复原为0
}
if (t == 0) { //此次循环进程不满足资源分配,则跳出循环返回错误
return false;
}
t = 0; //对下一次循环复原判断条件
}
return true;
}
bool requst() { //m是资源个数
int a, requst[M], flag=0, e=0; //e用于判断进程是否还需要资源
printf("输入请求的进程是第几位:");
scanf("%d", &a);
a--; //转化为角标
printf("请求向量为:");
for (int i = 0;i < m;i++) {
scanf("%d", &requst[i]);
}
for (int i = 0;i < m;i++) {
if (requst[i] > available[i] || requst[i] > need[a][i]) {
flag = 1;
}
}
if (flag == 1) {
printf("请求资源过大,无法分配资源\n");
return false;
}
else {
for (int i = 0;i < m;i++) { //尝试分配
allocation[a][i] += requst[i]; //分配资源增加
need[a][i] -= requst[i]; //需要资源减少
available[i] -= requst[i]; //可调用资源减少
}
for(int i = 0;i < n;i++){
finish[i] = false; //复原进程完成情况
}
for (int i = 0;i < m;i++) { //判断进程是否获得所有的需要资源
if(need[a][i] != 0){
e=1;
}
}
if (safety()) {
for (int i = 0;i < m;i++) { //复原
allocation[a][i] -= requst[i];
need[a][i] += requst[i];
available[i] = temp[i];
}
if(e==1){
for (int i = 0;i < m;i++) { //改变对应资源
allocation[a][i] += requst[i];
need[a][i] -= requst[i];
available[i] -= requst[i];
temp[i] = available[i];
}
}
else{
for (int i = 0;i < m;i++) { //改变对应资源
available[i] += allocation[a][i];
temp[i] = available[i];
allocation[a][i] = 0;
need[a][i] = 0;
}
}
printf("进程安全\n");
printf("进程安全序列为:");
for (int i = 0;i < n;i++) {
printf("P%d ", safe[i]);
}
safel = 0;
return true;
}
else {
for (int i = 0;i < m;i++) { //复原
allocation[a][i] -= requst[i];
need[a][i] += requst[i];
available[i] = temp[i];
}
printf("进程不安全\n");
return false;
}
}
}
void _scanf() { //输入
printf("请输入进程个数:");
scanf("%d", &n);
printf("请输入资源种类个数:");
scanf("%d", &m);
printf("\n");
for (int i = 0;i < n;i++) {
printf("请按照资源种类个数来输入数据:\n");
printf("进程%d的最大需求向量:",i+1);
for (int j = 0;j < m;j++) {
scanf("%d", &maxneed[i][j]);
}
printf("进程%d的分配向量:",i+1);
for (int j = 0;j < m;j++) {
scanf("%d", &allocation[i][j]);
}
printf("\n");
for (int j = 0;j < m;j++) {
need[i][j] = maxneed[i][j] - allocation[i][j];
}
}
printf("请输入可用资源向量:");
for (int i = 0;i < m;i++) {
scanf("%d", &available[i]);
temp[i] = available[i]; //用于后续复原available的数据
}
}
/*
void Sscanf() { //随机生成进程 ——》n,m不为5,3时 输出样式被破坏
printf("请输入进程个数:");
scanf_s("%d", &n);
printf("请输入资源个数:");
scanf_s("%d", &m);
printf("随机生成进程:\n");
srand(time(NULL));
for (int i = 0;i < n;i++) {
for (int j = 0;j < m;j++) {
maxneed[i][j] = rand() % 10;
}
for (int j = 0;j < m;j++) {
allocation[i][j] = 10000;
while(maxneed[i][j]< allocation[i][j]) { //保证随机生成的分配资源小于最大资源,特殊情况会出现need需求向量全零
allocation[i][j] = rand() % 10;
}
}
for (int j = 0;j < m;j++) {
need[i][j] = maxneed[i][j] - allocation[i][j];
}
}
}
*/
void _printf() { //输出
printf("\n资源分情况如图:\n");
printf(" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
printf(" 进程 | Max | Allocation | Need |\n");
for (int i = 0;i < n;i++) {
printf(" P%d ",i);
printf(" | ");
for (int j = 0;j < m;j++) {
printf("%d ", maxneed[i][j]);
}
printf(" | ");
for (int j = 0;j < m;j++) {
printf("%d ", allocation[i][j]);
}
printf(" | ");
for (int j = 0;j < m;j++) {
printf("%d ", need[i][j]);
}
printf(" | ");
printf("\n");
}
printf(" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
printf(" 可用资源Available为:");
for (int i = 0;i < m;i++) {
printf(" %d", available[i]);
}
printf("\n\n");
}
void menu() {
int i,t=1;
while (t) {
printf("\n");
printf(" 请选择:\n");
printf(" 0、退出系统\n");
printf(" 1、重启系统-->初始化\n");
printf(" 2、更改可用资源向量Available\n");
printf(" 3、新的请求向量-->安全性算法\n");
printf(" 4、查看此时进程数据\n");
printf(" 5、手动输入新的进程数据\n");
scanf("%d", &i);
if (i == 0) {
t = 0;
}
if (i == 1) {
Init();
_printf();
}
if (i == 2) {
printf("请输入可用资源向量:");
for (int i = 0;i < m;i++) {
scanf("%d", &available[i]);
temp[i] = available[i];
}
}
if (i == 3) {
if (requst()) {
printf("请求成功\n");
}
else {
printf("请求失败\n");
}
}
if (i == 4) {
_printf();
}
if(i==5){
_scanf();
_printf();
if (requst()) {
printf("请求成功\n");
}
else {
printf("请求失败\n");
}
}
if (i < 0 || i>5) {
printf("输入错误,请从新输入\n");
}
}
}
int main() {
Init();
_printf();
menu();
}
/* 测试数据
5
3
7 5 3 0 1 0
3 2 2 2 0 0
9 0 2 3 0 2
2 2 2 2 1 1
4 3 3 0 0 2
3 3 2
*/