- 问题描述
银行家算法用于确保在多进程环境中的资源分配是安全的。在这个问题中,有多个进程和多种类型的资源,进程可以提出资源请求,如果分配资源后系统仍然是安全的,那么资源分配就是合理的。
具体来说,每个进程都有最大需求矩阵(Max)、已分配矩阵(allocation)、需求矩阵(need)。系统中有可用资源向量(available)。每个进程可以请求资源,系统根据银行家算法判断是否分配资源是安全的。安全性检查的目标是确保系统能够在有限的步骤内为每个进程分配其最大需求的资源,而不会陷入死锁。
- 算法思想
银行家算法的核心思想是通过模拟分配资源并检查系统的安全性来判断是否允许分配。设定available、Max、allocation放在banker_data.txt中,先对进程提出的资源请求进行合法性检查,即检查请求的是否不大于需要的,是否不大于可利用的。 若请求合法,则进行模拟分配。最后对模拟分配后的状态调用安全性检查算法进行安全性检查。 若安全,则分配,否则,撤销分配,恢复原来状态,拒绝申请。用户可选择是否在已进行资源分配后的基础上再次进行资源请求。
- 算法流程
程序结构
(1)初始化init():读取banker_data.txt文件中资源可利用量、进程资源已分配量、进程最大需求量,并计算需求量。
(2)当前安全性检查check_safety():用于判断当前状态安全。
(3)银行家算法request():根据用户的资源请求,检查请求是否合法,如果合法则模拟分配资源并进行安全性检查,如果安全则返回true,否则撤销资源分配,返回false。
(4)显示当前状态print():显示成功资源分配后的详细情况。
(5)主程序main():逐个调用初始化、银行家算法函数、安全性检查、显示状态,使程序有序的进行。
安全性算法check_safety()函数
(1) 初始化:设置两个向量work[NUM_R]和finish[NUM_R]
work:系统可提供给进程继续运行所需各类资源数,初态赋值available。
finish:系统是否有足够资源分配给进程,初值false。
(2) 从进程中满足下面条件进程:
finish[i] = false; need[i][j] ≤ work[j];
若找到,执行(3),否则,执行(4)。
(3) 进程Pi获得资源,可顺利执行,完成释放所分配的资源。
work[j] += allocation[i,j]; finish[i] = true; go to (2)。
(4)若所有进程finish[i] = true,表示系统处于安全状态,输出安全序列,否则处于不安全状态。
流程图:
银行家算法request()函数
(1) 若 request[i] ≤ need[p_id][i]且request[i]≤ available[i],转向(2),否则请求不合理。
(2) 系统模拟把资源分配给进程Pi,修改下面数据:
available[i] -= request[i];
allocation[p_id][i] += request[i];
need[p_id][i] -= request[i];
(3)模拟分配后,执行安全性算法,检查此次分配后系统是否处于安全状态。若安全,则返回true;否则,此次模拟分配作废,撤销资源分配。
整体流程图:
- 结果与分析
本次作业示例采用的是课堂上的例子:
左图是雨课堂ppt,右图是banker_data.txt文件。
在banker_data.txt文件中第1行是各种资源的数量,第2~6行是各进程的最大需求,第7~11行是各进程已分配资源,可根据最大需求和已分配资源算出还需资源。用户可根据自己的需求创建新的banker_data.txt文件,此时,第1行是各种资源的数量,第2~NUM_P+1行是各进程对各资源的最大需求,第NUM_P+2~2NUM_P+1行是各资源对该进程的已分配资源。
输入进程数和资源数,读取banker_data.txt。输入进程ID和资源请求。
(1)T0之后的T1时刻P1请求资源request(1,0,2)。
分析:
①request(1,0,2) ≤ need(1,2,2),P1请求在最大需求范围内
request(1,0,2) ≤ available(3,3,2),可用资源可满足P1请求需要
②假定可为P1分配,修改available,allocation,need向量
available(2,3,0) = available(3,3,2)-request(1,0,2);
need(0,2,0) = need(1,2,2)-request(1,0,2);
allocation(3,0,2) =allocation(2,0,0)+request(1,0,2);
③利用安全性算法检查将资源分配后状态的安全性.
系统暂时先假定可为P1分配资源,并修改有关数据,
存在安全序列P1->P3->P0->P2->P4,此时系统是安全的,可将资源分配给进程P1.
分配成功后的资源:
Max | allocation | need | available | |
A B C | A B C | A B C | A B C | |
P0 | 7 5 3 | 0 1 0 | 7 4 3 | 2 3 0 |
P1 | 3 2 2 | 3 0 2 | 0 2 0 | |
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 |
(2) T1之后的T2时刻P4请求资源request(3,3,0)。
分析:
request(3,3,0)≤need4(4,3,1),P4请求在最大需求范围内。
request(3,3,0)≤available(2,3,0)不成立,即可用资源暂不能满足P4请求资源需要,P4阻塞等待。
P4请求资源Request(3,3,0)不合理,资源分配失败。
(3) T2之后的T3时刻P0请求资源request(0,2,0)。
分析:
①request(0,2,0)≤need(7,4,3);
request(0,2,0)≤available(2,3,0);
②假定可为P0分配,修改available,allocation,need向量
available(2,1,0) = available(2,3,0)-request(0,2,0);
need(7,2,3) = need(7,4,3)-request(0,2,0);
allocation(0,3,0) =allocation(0,1,0)+request(0,2,0);
③利用安全性算法检查将资源分配后状态的安全性
系统暂时先假定可为P0分配资源,并修改有关数据,
进行安全性检查,可用资源available(2,1,0)已不能满足任何进程的需要,故系统进入不安全状态,此时系统撤销分配资源,资源分配失败。
该算法能够保证在资源分配过程中不会导致系统陷入不安全状态,避免死锁的发生。算法的实现是一种保守的资源管理方法,确保系统状态的合法性。用户的资源请求需要满足系统的可用资源和进程的需求,否则请求将被拒绝。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int NUM_R,NUM_P,available[50], Max[50][50], allocation[50][50], need[50][50];
void init(const char *filename)
{
FILE *file = fopen(filename, "r");
if(file == NULL)
{
perror("Error opening file");
exit(1);
}
// 读取可用资源
for(int i = 0; i < NUM_R; i++)
fscanf(file, "%d", &available[i]);
// 读取最大需求矩阵
for(int i = 0; i < NUM_P; i++)
for (int j = 0; j < NUM_R; j++)
fscanf(file, "%d", &Max[i][j]);
// 读取分配矩阵
for(int i = 0; i < NUM_P; i++)
for(int j = 0; j < NUM_R; j++)
fscanf(file, "%d", &allocation[i][j]);
// 计算需求
for(int i = 0; i < NUM_P; i++)
for(int j = 0; j < NUM_R; j++)
need[i][j] = Max[i][j] - allocation[i][j];
fclose(file);
}
bool check_safety() //安全性检查
{
int work[NUM_R], security[NUM_P], k=0;
bool finish[NUM_P];
// 初始化work数组和finish数组
for(int i = 0; i < NUM_R; i++)
work[i] = available[i];
for(int i = 0; i < NUM_P; i++)
finish[i] = false;
// 找到一个未完成的进程,且其需求小于等于当前可用资源
for(int i = 0; i < NUM_P; i++)
{
int index = 0;
for(int j = 0; j < NUM_R; j++)
{
if(!finish[i] && need[i][j] <= work[j])
{
index++;//直到每类资源尚需数都小于系统可利用资源数才可分配
if(index == NUM_R)
{
for(int m = 0; m < NUM_R; m++)
work[m] += allocation[i][m];//更改当前可分配资源
finish[i] = true;
security[k++] = i;
i = -1; //保证每次查询均从第一个进程开始
}
}
}
}
for(int i=0;i<NUM_P;i++)
{
if(!finish[i])
{
printf("System is not safe\n");//不成功系统不安全
return false;
}
}
printf("System is safe\n");//如果安全,输出成功
printf("There is a security sequence:");
for(int i = 0; i < NUM_P; i++)
{//输出安全序列
printf("P%d",security[i]);
if(i<NUM_P-1)
printf("->");
}
printf("\n");
return true;
}
bool Request(int p_id, int request[NUM_R])
{
// 检查请求是否合法
for(int i = 0; i < NUM_R; i++)
{
if(request[i] > need[p_id][i] || request[i] > available[i])
{
printf("The resource request is unreasonable\n");
return false;
}
}
// 模拟分配资源
for(int i = 0; i < NUM_R; i++)
{
available[i] -= request[i];
allocation[p_id][i] += request[i];
need[p_id][i] -= request[i];
}
// 检查安全性
if (check_safety())
return true;
else
{
// 撤销分配
for (int i = 0; i < NUM_R; ++i)
{
available[i] += request[i];
allocation[p_id][i] -= request[i];
need[p_id][i] += request[i];
}
return false;
}
}
void print()
{
printf("Available resources: ");
for(int i = 0; i < NUM_R; i++)
printf("%d ", available[i]);
printf("\n");
printf("Max demand matrix:\n");
for(int i = 0; i < NUM_P; i++)
{
for(int j = 0; j < NUM_R; j++)
printf("%d ", Max[i][j]);
printf("\n");
}
printf("Allocation matrix:\n");
for(int i = 0; i < NUM_P; i++)
{
for(int j = 0; j < NUM_R; j++)
printf("%d ", allocation[i][j]);
printf("\n");
}
printf("Need matrix:\n");
for(int i = 0; i < NUM_P; i++)
{
for(int j = 0; j < NUM_R; j++)
printf("%d ", need[i][j]);
printf("\n");
}
}
int main()
{
printf("Please enter the number of processes and resources\n");
scanf("%d%d", &NUM_P, &NUM_R);
init("banker_data.txt");//需将内容提前输入到banker_data.txt中
int p_id, request[NUM_R], n;
while(1)
{
printf("Please enter the process ID\n");
scanf("%d", &p_id);
printf("Please enter a resource request\n");
for(int i = 0; i < NUM_R; i++)
scanf("%d", &request[i]); // 请求示例
if (Request(p_id, request))
{
printf("Resource allocation successful\n");
print();
}
else
printf("Resource allocation failed\n");
printf("Whether to request resources on this basis\n(1:yes 2:no)\n");
scanf("%d", &n);
if (n == 2)
break;
}
return 0;
}