银行家算法

银行家算法 C语言


前言

操作系统实验记录–银行家算法
一、实验目的
1)掌握安全性检测原理
2)掌握银行家算法

二、实验要求
1、要求学生进一步掌握如何 死锁的避免,进一步熟练使用数 组进行程序的设计及实现。
2、实现银行家算法、安全性检测算法。
3. 实验环境
1)每人一组,独立完成实验内容。
2)个人电脑1台,linux系统,安装gcc和vi等软件。

三、银行家算法中的数据结构:
1)可利用资源向量Available
2)最大需求矩阵Max
3)分配矩阵Allocation
4)需求矩阵Need。
安全性算法:
为每个进程分配所需要的资源,直至满足全部进程都能够顺利执行,不产生死锁。即能够找到满足全部进程执行的安全序列(路径)。
银行家算法:
如果进程申请的资源没有超过范围,先假定将该资源分配给该进程,而后更新相关数据机构,判断分配资源后系统是否安全。如果安全,则可以分配,反之则不分配。

四、算法流程图
在这里插入图片描述

一、银行家算法是什么?

必须学会1
必须学会2
看完之后,请日思夜想,你已经是一个银行家,在偌大事务中,你首先要解决的是银行家算法。怎么来衡量自己对该算法是否过关:
1.你的“巨有钱银行”面临了什么问题?提示:项目人申请借款,借吗?
2.借款的标准是什么?提示:申请是否合理,借了之后会不会倒闭?

二、C语言代码(ubuntu下运行,已成功)

关于写代码的经验,模仿别人的代码,把知识装进自己的脑子里。先熟悉整个代码逻辑,一个一个函数地去理解,先知道该函数的大概作用,然后在debug的过程中(也就是把每个函数调通的过程,可以使用printf()函数来调),加深理解。后面就可以很好地用起来了,百炼成钢!

1.实现效果

运行效果,可以自己输入不同的数据

2.代码及详细注释

//银行家算法完整版

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

char NAME[100] = {0};    //资源名称
int Available[100]={0};  //可用资源数
int Max[50][100]={0};    //各个进程最大需求资源
int Need[50][100] = {0}; //各个矩阵实时所需资源
int Allocation[50][100] = {0};  //实时分配资源
int Request[50]={0};            //请求分配资源

int N=100;   //设定的最大资源数
int M=50;    //设定的最大进程数

//初始设定,包括初始的资源名称,资源数,进程数
//各个进程最大需求资源,和对各个进程初始分配的资源数

void init(){
        int i=0,j=0,m=0,n=0;  //i,j用来做循环,n,m分别用来更新最大资源数和进程数
        int number=0,flag=0;  //number用作记录单个资源数,falg标识数据是否异常,1为异常
        char name=' ' ;       //记录进程名的变量
        int temp[100]={0};    //记录各类资源的使用情况

        printf("系统可用资源种类为(<100):\n");
        scanf("%d",&n);
        N = n;
        for(i=0;i<n;i++){
                printf("资源%d的名称:\n",i+1);
                getchar();           //这里地方一定要有,不然读不到name
                scanf("%c",&name);
                NAME[i] = name;

                printf("资源%c的初始个数为:\n",name);
                scanf("%d",&number);
                Available[i] = number;
        }

        printf("\n请输入进程的数量(<50):");
        scanf("%d",&m);
        M = m;
        printf("\n请输入各进程的最大需求矩阵的值[Max]:\n");
        do{
                flag = 0;
                for(i=0;i<M;i++){
                        for(j = 0;j <N;j++){
                                scanf("%d",&Max[i][j]);
                                if(Max[i][j]>Available[j]){
                                        flag = 1;
                                }
                        }
                }
                if(flag){
                        printf("\n资源最大需求量大于系统中资源最大量,请重新输入\n");

                }
        }while(flag);//获取合理的数据后退出


        do{
                flag = 0;
                printf("请输入各进程已经分配的资源量[Allocation]:\n");
                for(i=0;i<M;i++){
                        for(j = 0;j<N;j++){
                                scanf("%d",&Allocation[i][j]);
                                if(Allocation[i][j]>Max[i][j]){
                                        flag = 1;
                                }
                                Need[i][j] = Max[i][j] - Allocation[i][j];
                                temp[j] += Allocation[i][j];
                        }
                }
                if(flag){
                        printf("分配的资源大于最大需求量,请重新输入!\n");
                        for(j = 0;j <N;j++){
                                temp[j] = 0;   //这一步很重要,+=要及时清零                  
                        }
                }
        }while(flag);//获取合理数据


        for(j = 0;j<N;j++){
                Available[j] = Available[j] - temp[j];
                //更新可用资源,减去分配给进程的资源
        }
}

//输出初始化后的数据,调整格子的时候,让非制表符去适应制表符
//先在脑子里考虑整体,一个一个试t有点浪费时间
void showdata(){
        int i,j;
        printf("***************************************************************\n");
        printf("系统目前可用的资源[Available]:\n");
        for(i=0;i<N;i++){
                printf("%c\t",NAME[i]);
        }
        printf("\n");
        for(j=0;j<N;j++){
                printf("%d\t",Available[j]);
        }
        printf("\n");
        printf("系统当前的资源分配情况如下:\n");
        printf("\tMax  Allocation  Need\n");
        printf("进程名  ");
        for(j=0;j<3;j++){
                for(i = 0;i<N;i++){
                        printf("%c ",NAME[i]);
                }
                printf("\t ");
        }
        printf("\n");
                //把数据数出来以后要检查一下,三个矩阵有加减关系
        for(i = 0;i < M;i++){
                printf("P%d\t",i+1);
                for(j =0;j<N;j++){
                        printf("%d ",Max[i][j]);
                }
                printf("\t ");
                for(j =0;j<N;j++){
                        printf("%d ",Allocation[i][j]);
                }
                printf("\t ");
                for(j=0;j<N;j++){
                        printf("%d ",Need[i][j]);
                }
                printf("\n");
        }
}
//预分配
void test(int i){
        for(int j=0;j<N;j++){
                Available[j] = Available[j] - Request[j];
                Allocation[i][j] = Allocation[i][j] + Request[j];
                Need[i][j] = Need[i][j] - Request[j];
        }
}

//取消分配
void Retest(int i){
        for(int j =0;j<N;j++){
                Available[j] = Available[j] + Request[j];
                Allocation[i][j] = Allocation[i][j] - Request[j];
                Need[i][j] = Need[i][j] + Request[j];
        }
}


int Safe()
{
        int i,j,m,apply,k=0;    //这里必须给k赋值为0,因为后面没有k的初始化
        int Security[50]={0};   //安全序列
        int Finish[50] = {0};   //完成标志
        int Work[100] = {0};    //可用资源的替身

        for(j = 0;j<N;j++){
                                               Work[j] = Available[j];
        }
        for(i = 0;i <M;i++){
                Finish[i] = 0;  //一开始所有的都没完成
        }
        for(i=0;i<M;i++){
                apply=0;         //用来记录i进程中,是否所有资源都可需要
                for(j =0;j<N;j++){
                        if(Finish[i]==0 && Need[i][j]<=Work[j]){
                                //保证i进程需要的资源,现有资源都能满足
                                //并且i资源还没有完成
                                apply++;//这个是判断是不是所有资源都能被满足
                                if(apply==N){
                                        for(m=0;m<N;m++){
                                                Work[m]=Work[m] + Allocation[i][m];
                                                //i进程被c完成,回收分配给它的资源
                                        }
                                        Finish[i] = 1;//标志进程完成
                                        Security[k++] = i+1;   //先操作,后加
                                        //记录安全序列,+1是因为要从1开始
                                        i = -1;   //从头找起,尽量去完成所有任务
                                }
                        }
                }
        }

        for(i = 0;i <M;i++){
                if(Finish[i]==0){
                        printf("系统不安全\n");
                        return 0;
                }
        }
        printf("系统是安全的!\n");
        printf("存在一个安全序列:");
        for(i=0;i<M;i++){
                printf("P%d",Security[i]);//输出安全序列
                if(i<M-1){
                        printf("->");
                }
        }
        printf("\n");
        return 1;
} 
void bank(){
        int flag = 1;   //申请资源是否合理标识
        int i=0,j=0;

        printf("请输入请求分配资源的进程号(1-%d):",M);
        scanf("%d",&i);

        printf("请输入进程P%d要申请的资源个数:\n",i);
        for(j = 0;j<N;j++){
                printf("%c----",NAME[j]);
                scanf("%d",&Request[j]);
        }
        i = i-1;//涉及到输出的进程从1开始,看上去更自然,涉及矩阵从0开始
        for(j =0;j<N;j++){
                if(Request[j]>Need[i][j]){
                        printf("进程P%d申请的资源大于它需要的资源",i+1);
                        printf("分配不合理,不予分配!\n");
                        flag = 0;
                        break;
                }
                else if(Request[j]>Available[j]){
                        printf("进程%d申请的资源大于现有的资源",i+1);
                        printf("分配不合理,不予分配!\n");
                        flag = 0;
                        break;

                }
        }

        if(flag){ //合理只是第一个条件,接下来就是看是否安全
                test(i);
                if(Safe){
                         printf("准了!!");
                         showdata();
                }
                else if(!Safe()){
                        Retest(i);
                        showdata();
                }
        }
}
int main(){
        char choice;
        printf("\t--------------------------------------------\n");
        printf("\t||                                        ||\n");
        printf("\t||          银行家算法的实现              ||\n");
        printf("\t||                                        ||\n");
        printf("\t||                                        ||\n");
        printf("\t--------------------------------------------\n");
        init();
        showdata();
        if(!Safe()) {exit(0);}//避免一开始的要求就死锁


        do{
                printf("**********************************************\n");
                printf("\n");
                printf("\n");
                printf("\t---------------银行家算法演示---------------\n");
                printf("           R(r):请求分配              \n");
                printf("           E(e):退出                  \n");
                printf("\t--------------------------------------------\n");
                printf("请选择:\n");
                getchar();  //获取字符,程序就等着键盘
                scanf("%c",&choice);
                switch(choice){
                        case'r':
                        case'R':
                                bank();
                                break;
                        case'e':
                        case'E':
                                exit(0);
                }

        }while(choice);
        return 0;
}

三、调代码时遇到的错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

榆钱不知秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值