操作系统复习(三)处理机调度——三级调度体系 调度算法 死锁的概念及处理 c语言实现银行家算法


c语言实现银行家算法 

基本思想

在避免死锁的方法中,银行家算法是最具代表性的死锁算法。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。在分配资源之前,判断系统是否是安全的;若安全,才分配。

设计思路

1.调用init()函数初始化资源的基本信息(资源的种类数、资源的名字、每种资源的最大个数)和进程的基本信息(进程的个数、每个进程的名字、每个进程对每种资源的最大需求数)。如果输入的进程对资源的最大需求大于资源的最大数,则提示需求超过资源上限,并重新输入。

2.调用init_allocation()函数初始化分配状态,可以输入当前各个进程对各种资源的占有情况,如果输入大于该进程最大需求,则提示当前资源占用超过所需最大资源,并重新输入;如果输入大于资源最大数量,则提示当前资源占用超过资源上限,并重新输入。

3.更新需求矩阵和资源数量

4.输出资源矩阵、最大需求矩阵、已经分配矩阵和仍需分配矩阵。

5.调用allo方法,准备开始分配资源。首先输入进程名和所需各类资源数量,如果进程存在,请求资源数量小于仍需分配的数量,并且请求资源数量小于资源最大数量,则尝试分配,修改分配矩阵、仍需矩阵和资源矩阵,并调用safe方法判断是否安全,安全则分配成功,不安全则重置分配矩阵、仍需矩阵和资源矩阵。本程序尚未处理输入进程不存在的情况。

具体代码

//银行家算法

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//函数声明
void update();
intallo();
//全局变量
int  n;         //n表示资源的种类数
int  m;         //m表示进程


//结构体
struct info
{
    char name[20];
    int claim[50];     //各个进程所需资源的最大需求
    int allocation[50];//已经分配
    int need[50];      //仍需分配
    bool finish;       //满足标记
}pro[50];

struct rescource
{
    char name[20];
    int avaliable;//最大资源数
}resc[50],work[50];

void init()  
{   
    int i,j;
    int flag;
    printf("请输入资源种类数");
    scanf("%d",&n);

    for(i=0;i<n;i++)
    {
	printf("请输入第%d个资源的名字和最大资源数:\n",i+1);
	scanf("%s",&resc[i].name);
	scanf("%d",&resc[i].avaliable);
    }

    printf("请输入进程数:");
	scanf("%d",&m);	

    printf("\n");
    for(i=0;i<m;i++)       
    {
	printf("请输入第%d进程的名字和对各资源的最大需求数:\n",i+1);
	scanf("%s",&pro[i].name);
	pro[i].finish=false;
        for(j=0;j<n;j++)
	{
	    scanf("%d",&pro[i].claim[j]);
	    if(pro[i].claim[j]>resc[j].avaliable)
		flag=1;
	    else
	    {
		pro[i].allocation[j]=0;
                pro[i].need[j]=pro[i].claim[j];
		flag=0;
	    }
	    if(flag==1)
	    {
		i--;  
                printf("\n需求超过资源上限,请重新输入\n");  
	    }
	    getchar();
	}
    }
    printf("\n");
}


//初始分配状态
void init_allocation() 
{  
    int i,j;
    for (i = 0; i<m; i++) 
    {   
        int flag = 0;  
        printf("\n输入进程%d对当前各个资源占用情况", i + 1);  
        for (j = 0; j<n; j++) 
	{  
            scanf("%d", &pro[i].allocation[j]);  
            if (pro[i].allocation[j]>resc[j].avaliable) flag = 1;
	    if (pro[i].allocation[j]>pro[i].claim[j])   flag=2;
        }  
        if (flag == 1) 
	{  
            i--;  
            printf("\n当前资源占用超过资源上限,请重新输入\n");  
        }  
	else if(flag==2)
	{
	    i--;
	    printf("\n当前资源占用超过所需最大资源,请重新输入\n");
	}
    }  
update();  
}  


//更新需求矩阵need和资源数allocation  
void update()
{
    int i,j=0;
    for (i = 0; i<m; i++)
    {  
        for (j = 0; j<n; j++) 
	{  
            pro[i].need[j] = pro[i].claim[j] - pro[i].allocation[j]; //需求资源=最大需求-已经分配
            resc[j].avaliable-= pro[i].allocation[j];  //资源最大-=进程已经分配
        }  
    }  
}  

//绘制矩阵
void print() 
{  
    int i,j=0;
    printf("\n******资源矩阵如下******\n");  
    printf("名称\t数量\t\n");
    for (i = 0; i<n; i++) 
        printf("%s\t%d\t\n", resc[i].name,resc[i].avaliable);  

    printf("\n******最大需求矩阵******\n");
    for(i=0;i<m;i++)
    {
	printf("进程%s\t",pro[i].name);
	for(j=0;j<n;j++)
	    printf("%d\t",pro[i].claim[j]);
	printf("\n");
    }

    printf("\n******已经分配矩阵******\n");
    for(i=0;i<m;i++)
    {
	printf("进程%s\t",pro[i].name);
	for(j=0;j<n;j++)
            printf("%d\t",pro[i].allocation[j]);
	printf("\n");
    }

    printf("\n******仍需矩阵******\n");  
    for(i=0;i<m;i++)
    {
        printf("进程%s\t",pro[i].name);
	for(j=0;j<n;j++)
	    printf("%d\t",pro[i].need[j]);
	printf("\n");
    }
    printf("\n");     
}  

intsafe()
{  
    int i=0,j=0;
    int back=1;
    for(i=0;i<n;i++)
    {
	strcpy(work[i].name,resc[i].name);
	work[i].avaliable=resc[i].avaliable;
    }
    printf("正在尝试建立安全队列\n");
    for(i=0;i<m;i++)
    {
	if(pro[i].finish==false)
	{
	    for(j=0;j<n;j++)
	    {
		if(pro[i].need[j]<=work[j].avaliable)
		{
		    work[j].avaliable=work[j].avaliable;
		    pro[i].finish=true;
		}
		else
		{
		    pro[i].finish=false;
		    printf("在进程%s处出现不安全情况,安全队列无法建立",pro[i].name);
		    break;
		}
	    }
			
	}
    }
    for(i=0;i<n;i++)
	if(pro[i].finish==false)
          back=0;
return back;
}


int index(char tname[20])
{
    int i=0;
    for(i=0;i<m;i++)
    {
        if(strcmp(pro[i].name,tname)==0)
	    return i;
    }
    return -1;
}


//分配函数
int allo()    
{
    int next;
    char temp_pro_name[20];    //临时进程名
    struct rescourcetresc[50];
    int i=0;
    int back_pro=m;
    int back=0;
    printf("开始分配吗,开始输入1否则输入0");
	scanf("%d",&next);
    do{
	printf("\n请输入进程名,并依次输入所需资源数量\n");
	scanf("%s",&temp_pro_name);
	for(i=0;i<n;i++)
	{
	    scanf("%d",&tresc[i].avaliable);
	}
        back_pro=index(temp_pro_name);   //返回进程的下标
	if(back_pro!=-1)
	{
	    for(i=0;i<n;i++)
	    {
                printf("准备开始为进程%s分配资源\n",pro[back_pro].name);
	        if(tresc[i].avaliable<=pro[back_pro].need[i])//请求小于等于仍需
		{
                    if(tresc[i].avaliable<=resc[i].avaliable)//请求小于
		    {
                        pro[back_pro].allocation[i]=pro[back_pro].allocation[i]+tresc[i].avaliable;
		        pro[back_pro].need[i]=pro[back_pro].need[i]-tresc[i].avaliable;
			resc[i].avaliable=resc[i].avaliable-tresc[i].avaliable;
		    }
		    else
		    {
                        printf("\n资源%s当前已经不足%d个",resc[i].name,tresc[i].avaliable);
                         break;
		    }
		}
                else
		{
	            printf("进程%s已经不需要%s资源%d个",temp_pro_name,resc[i].name,tresc[i].avaliable);
	            break;
		}
	    }
        }
        else
        printf("进程尚不存在");

        back=safe();
        if(back==0)//不安全
        {
            for(i=0;i<n;i++)
	    {
                pro[back_pro].allocation[i]=pro[back_pro].allocation[i]-tresc[i].avaliable;
	        pro[back_pro].need[i]=pro[back_pro].need[i]+tresc[i].avaliable;
	        resc[i].avaliable=resc[i].avaliable+tresc[i].avaliable;
	    }
	    printf("\n系统可能会处于不安全状态,本次请求失败");
	    print();
        }
        else if(back==1)    
        {
	    printf("\n分配成功");
	    print();
        }
    }while(next==1);

    return 0;
}


//主函数
void main()
{ 
    int i;
    init();           //初始化进程和资源的信息
    printf("-------------------------------------");
    init_allocation();//初始化进程对资源的占用情况
    print();          //输出各个矩阵
    do
    {
	printf("选择1--用银行家算法;选择0--退出");
        scanf("%d",&i);
        if(i==1)
	{
	   allo();
	}
    }while(i==1);
}

参考结果

1.初始化时输入进程所需资源数大于资源最大数

2.初始化时进程对资源的占用情况大于进程所需

3.初始化时进程对资源的占用大于资源最大可用

4.初始化成功

5.进程请求资源时大于自己仍需资源数

6.分配失败

7.分配成功

猜你喜欢

转载自blog.csdn.net/shujian_tianya/article/details/81989953