操作系统–银行家算法(C语言实现)
一.简介
银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
二.安全序列
如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
三.数据结构
- 可利用资源向量Available 。这是一个含有m个元素的数组, 其中每一个元素代表一类可以利用的资源数目。其初始值是系统中所配置的该类全部可用资源的数目,其数值随着该类资源的分配和回收而动态改变,如果Available[j] = k 则表示系统中现在有Rj 类资源的最大数目为K。
- 最大需求矩阵Max 。 这是一个 n x m 的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求量。 如果Max[i,j] = K , 则表示进程i需要Rj 类资源的最大数目为k。
- 分配矩阵Allocation 。 这也是一个n x m 的矩阵, 它定义了系统中每一类资源当前已分配给每一进程的资源数。如果 Allocation[i,j] =K ,则表示进程i当前已分得Rj 类资源的数目为K。
- 需求矩阵 Need 。 这也是一个n x m 的矩阵。用以表示每一个进程尚需的各类资源数, 如果Need[i,j] = K , 则表示进程i还需要Rj 类资源K个才能完成该任务。
上述三个矩阵存在着下述关系:
Need[i,j] = Max[i,j] - Allocation[i,j]
四.银行家算法
设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 ] - Request[ j ] ;
Allocation[i , j] = Allocation[i , j] + Request[ j ] ;
Need[ i , j ] = Need[ i , j] - Request[ j ] ;
(4) 系统执行安全性算法, 检查此次资源分配后系统是否处于安全状态,若安全,才正式将资源分配给进程Pi , 以完成本次分配, 否则, 将本次试探分配作废 , 恢复原来的资源分配状态 , 并且Pi等待。
Available[ j ] = Available[ j ] + Request[ j ] ;
Allocation[i , j] = Allocation[i , j] - Request[ j ] ;
Need[ i , j ] = Need[ i , j] - Request[ j ] ;
五.安全性算法
系统所执行的安全性算法可描述如下:
(1) 设置两个向量 : 1.工作向量Work , 它表示系统可提供给进程继续执行所需要的各类资源数目, 它含有m个元素, 在执行安全算法开始时,Work = Available ; 2. Finish:它表示系统是否有足够的资源分配给进程, 使之运行完成, 开始时先做Finish[ i ] = false ; 当有足够多的资源分配给进程时。再 令finish[i] =ture 。
(2) 从进程集合中找到一个能满足下述条件的进程:
1.Finish [ i ] = fasle;
2.Need[ i , j ] <= Work[ j ];
(3) 当进程Pi获得资源后, 可顺利执行, 直到完成, 并释放分配给它的资源,故应该执行:
Work[ j ] = Work[ j ] + Allocation [ i , j ];
Finnish[ i ] = true;
go to step 2;
( 4 ) 如果所有进程的Finish [ i ] = true ; 则表示系统处于安全状态, 否则 系统处于不安全状态。
六.算法实现
输入函数 ------用户手动输入Max矩阵 ,Allocation矩阵,可用资源数
void input(){
printf("请输入进程的个数:");
scanf("%d",&process_number);
printf("请输入资源种类的个数:");
scanf("%d",&resource_number);
printf("请输入进程的max矩阵(%dX%d):",process_number,resource_number);
for(int i = 0 ; i< process_number;i++){
for(int j = 0 ; j < resource_number;j++){
scanf("%d",&MAX[i][j]);
}
}
printf("请输入ALLOCATION矩阵(%dX%d):",process_number,resource_number);
for(int i = 0 ; i< process_number;i++){
for(int j = 0 ; j < resource_number;j++){
scanf("%d",&ALLOCATION[i][j]);
NEED[i][j] = MAX[i][j] - ALLOCATION[i][j]; //计算出需求矩阵,还需要的资源的个数
//检查NEED矩阵的值是否异常
if(NEED[i][j] <0){
printf("您输入的第%d个进程的第%d个资源错误,请重新输入",i,j);
j--;
continue;
}
}
}
printf("请输入现在可用的各种资源的个数(AVAIVABLE):");
for(int i = 0; i<resource_number;i++){
scanf("%d",&AVAIVABLE[i]);
}
}
计算安全序列–若安全则返回安全序列,不安全则提示
bool isSafe(){//计算安全序列
int work[resource_number] ;//工作数组
//将AVAIVABLE的值传给work
for(int i = 0 ; i<resource_number ; i++){
work[i] = AVAIVABLE[i];
}
//初始化finish数组 将值都改成fasle 默认线程不能释放资源
for(int i = 0 ; i< process_number;i++){
FINISH[i] = false;
}
//寻找安全序列
int flag,k ; //定义一个标记 如果每轮都有进程释放资源 则flag = i - 1
for(int i = 0;i< process_number; i++){
flag = i;
for(int j = 0 ; j< process_number;j++){
//判断进程的finish值 如果为true 则证明此进程已经释放资源,即跳过本轮循环
if(FINISH[j] == true){
continue;
}
/*否则就是该进程改为释放资源 则需要与现存可用的资源数比较,
判断现存资源能否使之运行完毕,若不行则不处理 等待下一轮循环*/
for( k = 0 ; k< resource_number;k++){
if(NEED[j][k] > work[k]){
break;
}
}
if(k == resource_number ){//满足条件则表示现在可用资源能满足该进程需求 则释放资源
FINISH[j] = true;
for (k = 0; k < resource_number; k++) //n为资源种类的数目
{
work[k] += ALLOCATION[j][k];
}
p[i++] = j; //记录进程号
}else //如果超过继续循环下一个进程
{
continue;
}
}
if (i == flag)
{
printf("系统不安全");
return false;
}
}
printf("系统是安全的\n");
printf("安全序列为:");
for (int i = 0; i < resource_number; i++)
{
printf("%d",p[i]);
if (i != process_number - 1)
{
printf("-->");
}
}
printf("");
return true;
}
全部代码
#include<stdio.h>
//宏定义确认Max矩阵 ALLOCATION矩阵
#define PROCESS_MAX 20 //记录用户数据的最大进程数
#define RESOURCE_MAX 20 //记录用户输入的最大资源种类个数
int MAX[PROCESS_MAX][RESOURCE_MAX];//MAX矩阵 最大资源需求量
int ALLOCATION[PROCESS_MAX][RESOURCE_MAX]; //已分配矩阵 已分配的资源个数
int AVAIVABLE[RESOURCE_MAX];//记录现在可用的各种资源的数目
int NEED[PROCESS_MAX][RESOURCE_MAX];//需求矩阵
bool FINISH[PROCESS_MAX];
int process_number; //记录用户输入的进程数
int resource_number;//记录用户输入的资源个数
int p[PROCESS_MAX]; /*记录序列*/
void input(); //函数声明
bool isSafe();
int main(){
input();
isSafe();
return 0 ;
}
void input(){
printf("请输入进程的个数:");
scanf("%d",&process_number);
printf("请输入资源种类的个数:");
scanf("%d",&resource_number);
printf("请输入进程的max矩阵(%dX%d):",process_number,resource_number);
for(int i = 0 ; i< process_number;i++){
for(int j = 0 ; j < resource_number;j++){
scanf("%d",&MAX[i][j]);
}
}
printf("请输入ALLOCATION矩阵(%dX%d):",process_number,resource_number);
for(int i = 0 ; i< process_number;i++){
for(int j = 0 ; j < resource_number;j++){
scanf("%d",&ALLOCATION[i][j]);
NEED[i][j] = MAX[i][j] - ALLOCATION[i][j]; //计算出需求矩阵,还需要的资源的个数
//检查NEED矩阵的值是否异常
if(NEED[i][j] <0){
printf("您输入的第%d个进程的第%d个资源错误,请重新输入",i,j);
j--;
continue;
}
}
}
printf("请输入现在可用的各种资源的个数(AVAIVABLE):");
for(int i = 0; i<resource_number;i++){
scanf("%d",&AVAIVABLE[i]);
}
}
bool isSafe(){//计算安全序列
int work[resource_number] ;//工作数组
//将AVAIVABLE的值传给work
for(int i = 0 ; i<resource_number ; i++){
work[i] = AVAIVABLE[i];
}
//初始化finish数组 将值都改成fasle 默认线程不能释放资源
for(int i = 0 ; i< process_number;i++){
FINISH[i] = false;
}
//寻找安全序列
int flag,k ; //定义一个标记 如果每轮都有进程释放资源 则flag = i - 1
for(int i = 0;i< process_number; i++){
flag = i;
for(int j = 0 ; j< process_number;j++){
//判断进程的finish值 如果为true 则证明此进程已经释放资源,即跳过本轮循环
if(FINISH[j] == true){
continue;
}
/*否则就是该进程改为释放资源 则需要与现存可用的资源数比较,
判断现存资源能否使之运行完毕,若不行则不处理 等待下一轮循环*/
for( k = 0 ; k< resource_number;k++){
if(NEED[j][k] > work[k]){
break;
}
}
if(k == resource_number ){//满足条件则表示现在可用资源能满足该进程需求 则释放资源
FINISH[j] = true;
for (k = 0; k < resource_number; k++) //n为资源种类的数目
{
work[k] += ALLOCATION[j][k];
}
p[i++] = j; //记录进程号
}else //如果超过继续循环下一个进程
{
continue;
}
}
if (i == flag)
{
printf("系统不安全");
return false;
}
}
printf("系统是安全的\n");
printf("安全序列为:");
for (int i = 0; i < resource_number; i++) //改了146行的i值,显示资源分配给进程的顺序
{
printf("%d",p[i]);
if (i != process_number - 1)
{
printf("-->");
}
}
printf("");
return true;
}