操作系统–银行家算法(C语言实现)

一.简介

银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

二.安全序列

如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。

三.数据结构

  1. 可利用资源向量Available 。这是一个含有m个元素的数组, 其中每一个元素代表一类可以利用的资源数目。其初始值是系统中所配置的该类全部可用资源的数目,其数值随着该类资源的分配和回收而动态改变,如果Available[j] = k 则表示系统中现在有Rj 类资源的最大数目为K。
  2. 最大需求矩阵Max 。 这是一个 n x m 的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求量。 如果Max[i,j] = K , 则表示进程i需要Rj 类资源的最大数目为k。
  3. 分配矩阵Allocation 。 这也是一个n x m 的矩阵, 它定义了系统中每一类资源当前已分配给每一进程的资源数。如果 Allocation[i,j] =K ,则表示进程i当前已分得Rj 类资源的数目为K。
  4. 需求矩阵 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;

   
}