银行家算法——C语言实现

算法思路

将操作系统看作是银行家,操作系统所拥有的资源就相当于银行家所拥有的资产,进程向操作系统申请资源就相当于资产家向银行贷款,规定资产家在向银行贷款之前,先申明其所贷数额的最大值,申明之后其贷款的数额不得超过此最大值,而银行家应该合理安排贷款给各个资产家的顺序,以保证银行不会破产;显然将钱全部分配给一位资本家是十分不合理的这样银行家将承担很大的风险;

算法所用到的数据结构

  1. max[ ][ ]:用于记录进程对系统中各个资源的最大需求量,如max[i][j]表示第i个进程对系统中的Rj资源的最大需求量
  2. allocation[ ][ ]:表示各个进程已经分配到的资源的数目,比如allocation[i][j]表示第i个进程目前分配到资源Rj的数目
  3. available[ ]:表示目前系统中各个资源可用的数量,比如available[i]表示资源Ri此时的可用数量
  4. need[ ][ ]:表示进程此时还需要的各个资源的数量,如need[i][j]表示第i个进程还需要的Rj的资源的数目,显然:need[i][j]=max[i][j]-allocation[i][j];

算法步骤 

假设系统中有三类资源A,B,C,各个资源的数目已知,若此时进程Pi向系统申请资源,其资源申请向量为requesti(x,y,z),即进程i需要A类资源数目x,B类资源数目y,C类资源数目z

  1. 第一步若requesti>need[i](只要存在j,使得requesti[j]>need[i][j],那么此不等式便成立) ,则表明进程i所申请的资源数目大于其一开始所声明的最大值,系统对其请求不予理睬,若此不等式不成立,则继续执行下一步;
  2. 第二步根据allocation数组计算出available,如果request>available(只要存在j,使得requesti[j]>available[j],那么此不等式便成立) ,若该不等式成立则表明此时系统中的剩余资源数目不能满足进程i的请求,进程i必须阻塞等待,若该不等式不成立则继续执行下一步;
  3. 第三步,尝试着将进程i所需要的资源分配给进程i,然后检测若将进程i所需要的资源分配给进程i之后会不会导致系统进入不安全的状态,若不会导致系统进入不安全状态,那么就正式将资源分配给进程i,否则就要将刚刚尝试分配给进程i的资源回收,拒绝进程i的资源请求

上诉算法最关键的一部是最后一步的判断此时系统是否处于安全状态,于是接着介绍系统安全性检测算法

安全性检测算法 

  1. 设置数组work[ ],work数组的初始值是available
  2. 将work[i]数组与need[i[进行比较,若满足work[i]>need[i]那么边将进程i添加到安全序列里面,若不满足则继续扫面下一个进程是否满足此不等式,若满足,则改变work数组的值:work[j]+=allocation[i][j],然后从第一个进程开始扫描,看当改变了work之后是否新增进程满足条件
  3. 若最后安全序列中含有系统中全部的进程那么就说此时系统是安全的

算法源代码

算法详细思路在代码注释中给出

#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS//需要解决的问题:
//1.根据系统现在的状态判断系统现在是不是安全的
//2.当某一个进程像系统请求资源时,判断此时系统应不应该将此资源分配给他#define RESOURCE_NUM 3
#define PROCESS_NUM 5#define true 1
#define false 0//定义系统拥有的各种资源的数量
int maxResource[RESOURCE_NUM];//定义系统中剩余可用的资源数目
int available[RESOURCE_NUM];//定义安全检测时的work数组
int work[RESOURCE_NUM];//定义系统中现在已经分配给各个进程的资源数目
int allocation[PROCESS_NUM][RESOURCE_NUM];//定义各个进程对资源的最大需求量
int maxNeeds[PROCESS_NUM][RESOURCE_NUM];//定义各个进程还需要的各个资源的数目
int stillNeeds[PROCESS_NUM][RESOURCE_NUM];//用于定义系统中存在的安全序列
int securitySequence[PROCESS_NUM];//isEnougth[i]表示系统中的剩余资源可以满足进程i还需要的资源数目
int isEnough[PROCESS_NUM];//定义用于对各个数组模块进行初始化的函数
void initialize();//用于打印目前系统的资源分配情况
void outAllocation();//用于求解stillNeeds函数
void solveNeeds();//用于求解系统中剩余资源数目的函数
void solveAvailable();//定义打印安全序列的代码
void print();//安全性检测算法
int securityTest();//定义用于给请求进程进行资源分配的函数
int dispense();//定义用于将分配给某个进程的资源回收的函数
int restore();//银行家算法,用于判断当此时系统中有进程申请系统资源时能不能将其所申请的资源分配给他
void banker();//用于记录此时是那个进程请求系统为其分配资源
int requestProcess;   //用于记录进程所请求的各种系统资源的数目
int request[RESOURCE_NUM];  int main()
{initialize();//打印当前系统的资源分配情况outAllocation();printf("\n\n");banker();printf("\n\n");//执行银行家算法之后由于可能给某个进程分配了资源,于是再次打印系统目前的资源分配清苦outAllocation();return 0;
}void solveNeeds()
{for (int i = 0; i < PROCESS_NUM; i++){for (int j = 0; j < RESOURCE_NUM; j++){stillNeeds[i][j] = maxNeeds[i][j] - allocation[i][j];}}
}void solveAvailable()
{for (int i = 0; i < RESOURCE_NUM; i++){available[i] = maxResource[i];}for (int j = 0; j < RESOURCE_NUM; j++)    //j表示列{for (int i = 0; i < PROCESS_NUM; i++)    //i表示行{available[j] -= allocation[i][j];}}
}void initialize()
{//初始化系统中各个资源的数量printf("请输入系统中各种资源的数量:\n");for (int i = 0; i < RESOURCE_NUM; i++){scanf("%d", &maxResource[i]);}//初始化各个进程对系统中各个资源的最大需求量for (int i = 0; i < PROCESS_NUM; i++){printf("请输入进程%d对系统中各种资源的最大需求量:\n", i);for (int j = 0; j < RESOURCE_NUM; j++){scanf("%d", &maxNeeds[i][j]);}}//初始化allocation矩阵for (int i = 0; i < PROCESS_NUM; i++){printf("系统已经分配给进程%d的各种资源的数量:\n", i);for (int j = 0; j < RESOURCE_NUM; j++){scanf("%d", &allocation[i][j]);}}//初始化需求矩阵solveNeeds();//初始化available数组solveAvailable();//初始化work数组for (int i = 0; i < RESOURCE_NUM; i++){work[i] = available[i];}//初始化isEnough数组for (int i = 0; i < PROCESS_NUM; i++){isEnough[i] = false;}printf("请输入当前是哪一个进程在向系统申请资源\n");scanf("%d", &requestProcess);printf("请输入进程%d向系统申请的各个资源的数目\n", requestProcess);for (int i = 0; i < RESOURCE_NUM; i++){scanf("%d", &request[i]);}
}void outAllocation()
{printf("**************************************************************************************************\n");printf("当前系统的资源分配情况如下:\n");printf("\t\tmaxNeeds\t\tallocation\t\tstillNeeds\t\tavailable\n");printf("资源名称\t");for (int i = 0; i < 4; i++){if (i == 3){for (int j = 0; j < RESOURCE_NUM; j++){printf("%d ", available[j]);}}else{printf("A B C");printf("\t\t\t");}}printf("\n");for (int j = 0; j < PROCESS_NUM; j++){printf("P%d\t\t",j);for (int k = 0; k < RESOURCE_NUM; k++){printf("%d ", maxNeeds[j][k]);}printf("\t\t\t");for (int k = 0; k < RESOURCE_NUM; k++){printf("%d ", allocation[j][k]);}printf("\t\t\t");for (int k = 0; k < RESOURCE_NUM; k++){printf("%d ", stillNeeds[j][k]);}printf("\n");}printf("**************************************************************************************************\n");
}void print()
{for (int i = 0; i < PROCESS_NUM; i++){if (i == PROCESS_NUM - 1)printf("%d", securitySequence[i]);elseprintf("%d->", securitySequence[i]);}printf("\n");
}int securityTest()
{int count = 0;  //用于记录安全序列中已经添加了多少个进程for (int i = 0; i < PROCESS_NUM; i++){int flag = 1;  //用于标记是否使用break语句跳出了内层循环for (int j = 0; j < RESOURCE_NUM; j++){if (work[j] < stillNeeds[i][j]){flag = 0;break;}}//若isEnough[i]=0表示此时的进程i还没有被加入到安全序列中,那么便可以将其加入到安全序列中if (flag == 1 && isEnough[i] == false){//将进程i添加到安全序列中securitySequence[count] = i;count++;//修改isEnough[i]的值为true,有两层含义,第一层含义是代表此时进程i已经进入安全序列了,下一次循环检测时若检测到进程i便可以不用重复将其加入到安全序列中//第二层含义,是最后用于判定系统是否安全的依据,只有isEnough数组中全部的元素的值都是1才代表着此系统是安全的否则系就处于不安全的状态isEnough[i] = true;//当安全序列中新增进程之后,需要改变available数组的值for (int k = 0; k < RESOURCE_NUM; k++){work[k] += allocation[i][k];}i = -1;//保证可以从头开始遍历所有的进程//注意此条语句的位置必须位于此,因为只有安全序列中添加了新元素之后,available数组的值才会改变,此时才需要重新扫描所有进程看如今系统中剩余的资源是否可以满足以前不能满足的进程}}//检查系统此时是否处于安全状态for (int i = 0; i < PROCESS_NUM; i++){if (isEnough[i] == false) {return false;}}return true;}int dispense()
{//尝试将资源分配给请求进程的时候,发生改变的数组有,allocation,stillNeeds,available,work;for (int i = 0; i < RESOURCE_NUM; i++){allocation[requestProcess][i] += request[i];stillNeeds[requestProcess][i] -= request[i];available[i] -= request[i];work[i] -= request[i];}
}int restore()
{for (int i = 0; i < RESOURCE_NUM; i++){allocation[requestProcess][i] -= request[i];stillNeeds[requestProcess][i] += request[i];available[i] += request[i];work[i] += request[i];}
}void banker()
{//第一步检查进程所申请的资源数目是否超过其一开始声明的最大值for (int i = 0; i < RESOURCE_NUM; i++){if (request[i] > stillNeeds[requestProcess][i]){printf("进程%d所申请的资源已经超过了其一开始定义的最大值,不予分配\n");return;}}//第二检查系统中剩余的资源是满足进程的请求for (int i = 0; i < RESOURCE_NUM; i++){if (request[i] > available[i]){printf("系统资源不足,分配失败,请进程阻塞等待\n");return;}}//尝试分配资源dispense();//分配完资源之后判断系统是否处于安全状态,若处于安全状态则就真正的将资源分配给请求的进程,否则就将刚才预分配的资源恢复if (securityTest()){printf("此次分配不会导致系统进入不安全状态,分配成功!\n");//输出此时的安全序列printf("此时系统的其中一个安全序列为:\n");print();return;}else{printf("此次分配将会使得系统进入不安全状态,拒绝分配\n");restore();return;}
}

运行结果截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/86130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构与算法-时间复杂度与空间复杂度

数据结构与算法 &#x1f388;1.概论&#x1f52d;1.1什么是数据结构&#xff1f;&#x1f52d;1.2什么是算法&#xff1f; &#x1f388;2.算法效率&#x1f52d;2.1如何衡量一个算法的好坏&#xff1f;&#x1f52d;2.2算法的复杂度&#x1f52d;2.3时间复杂度&#x1f4d6;2…

软件设计师考试学习2

数据结构与算法基础 数组 稀疏矩阵 用代入法计算&#xff0c;A 数据结构的定义 非线性结构分为树和图&#xff0c;区别在于有没有环路 顺序表与链表 引入头节点可以使所有的节点处理方式一致 如果没有空的头节点&#xff0c;头节点需要单独处理 顺序存储与链式存储 查找…

AI-Chat,一款集全网ai功能的应用(附下载链接)

AI-Chat是一款综合性的聊天机器人&#xff0c;集成了多种先进的模型和功能。它采用了GPT4.0、联网版GPT和清华模型等多种模型&#xff0c;使得其具备更强大的语言处理能力。同时&#xff0c;AI-Chat还融合了AI绘画模型&#xff0c;例如Stable Diffusion绘画、文生图、图生图、艺…

基于下垂控制的并网逆变器控制MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主要模块&#xff1a; 建议使用MATLAB2021b及以上版本打开&#xff01; 功率计算模块、下垂控制模块、电压电流双环控制模块、虚拟阻抗压降模块 扰动设置&#xff1a; 在0.5秒到2秒始端设置0.25Hz的电网频…

手机上网流程解析

来看一个手机开机之后上网的流程&#xff0c;这个过程称为 Attach。可以看出来&#xff0c;移动网络还是很复杂的。因为这个过程要建立很多的隧道&#xff0c;分配很多的隧道 ID&#xff0c;所以我画了一个图来详细说明这个过程。 1、手机开机以后&#xff0c;在附近寻找基站 e…

Hadoop源码阅读(三):HDFS上传

说明&#xff1a; 1.Hadoop版本&#xff1a;3.1.3 2.阅读工具&#xff1a;IDEA 2023.1.2 3.源码获取&#xff1a;Index of /dist/hadoop/core/hadoop-3.1.3 (apache.org) 4.工程导入&#xff1a;下载源码之后得到 hadoop-3.1.3-src.tar.gz 压缩包&#xff0c;在当前目录打开Pow…

2023华为杯数学建模竞赛E题

一、前言 颅内出血&#xff08;ICH&#xff09;是由多种原因引起的颅腔内出血性疾病&#xff0c;既包括自发性出血&#xff0c;又包括创伤导致的继发性出血&#xff0c;诊断与治疗涉及神经外科、神经内科、重症医学科、康复科等多个学科&#xff0c;是临床医师面临的重要挑战。…

Python之网络编程

一、网络编程 互联网时代,现在基本上所有的程序都是网络程序,很少有单机版的程序了。 网络编程就是如何在程序中实现两台计算机的通信。 Python语言中,提供了大量的内置模块和第三方模块用于支持各种网络访问,而且Python语言在网络通信方面的优点特别突出,远远领先其他语…

KT142C语音芯片flash型用户如何更新固件的说明_V2

目录 一、简介 2.1 让芯片进入PC模式 2.2 双击提供的exe程序即可 一、简介 正常的情况下&#xff0c;用户肯定是不需要更新固件的&#xff0c;因为芯片出厂默认就烧录了对应的程序固件&#xff0c;但是有客户可能需要小修小改&#xff0c;或者订制一下某些功能&#xff0c…

Linux设备驱动之Camera驱动

Linux设备驱动之Camera驱动 Camera&#xff0c;相机&#xff0c;平常手机使用较多&#xff0c;但是手机的相机怎么进行拍照的&#xff0c;硬件和软件&#xff0c;都是如何配合拍摄到图像的&#xff0c;下面大家一起来了解一下。 基础知识 在介绍具体Camera框架前&#xff0c…

Linux——进程

目录 一、基本概念 二、描述进程-PCB &#xff08;一&#xff09;task_struct-PCB的一种 &#xff08;二&#xff09;task_ struct内容分类 三、查看进程 &#xff08;一&#xff09;利用ps命令 &#xff08;二&#xff09; 通过 /proc 系统文件夹查看 &#xff08;三…

停车场系统源码

源码下载地址&#xff08;小程序开源地址&#xff09;&#xff1a;停车场系统小程序&#xff0c;新能源电动车充电系统&#xff0c;智慧社区物业人脸门禁小程序: 【涵盖内容】&#xff1a;城市智慧停车系统&#xff0c;汽车新能源充电&#xff0c;两轮电动车充电&#xff0c;物…

zemaxMIF曲线图

调制传递函数&#xff08; Modulation Transfer Function&#xff0c;MTF &#xff09;是用来形容光学系统成像质量的重要指标。 通过对光学系统像空间进行傅里叶变换&#xff0c;可以得到一张分析图表&#xff0c;来描述像面上对比度和空间频率之间的对应关系。 对比度&…

C/C++统计满足条件的4位数个数 2023年5月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C统计满足条件的4位数个数 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 C/C统计满足条件的4位数个数 2019年12月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 给定若干…

numpy 和 tensorflow 中的各种乘法(点乘和矩阵乘)

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都准备好了&#xff0c;直接在文末名片自取就可 点乘和矩阵乘…

【深度学习实验】前馈神经网络(三):自定义多层感知机(激活函数logistic、线性层算Linear)

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集 2. 激活函数logistic 3. 线性层算子 Linear 4. 两层的前馈神经网络MLP 5. 模型训练 一、实验介绍 本实验实现了一个简单的两层前馈神经网络 激活函数…

Linux 链表示例 LIST_INIT LIST_INSERT_HEAD

list(3) — Linux manual page 用Visual Studio 2022创建CMake项目 * CmakeLists.txt # CMakeList.txt : Top-level CMake project file, do global configuration # and include sub-projects here. # cmake_minimum_required (VERSION 3.12)project ("llist")# I…

云原生Kubernetes:K8S存储卷

目录 一、理论 1.存储卷 2.emptyDir 存储卷 3.hostPath卷 4.NFS共享存储 5.PVC 和 PV 6.静态创建PV 7.动态创建PV 二、实验 1.emptyDir 存储卷 2.hostPath卷 3.NFS共享存储 4.静态创建PV 5.动态创建PV 三、问题 1.生成pod一直pending 2.shoumount -e未显示共享…

YOLOv5如何训练自己的数据集

文章目录 前言1、数据标注说明2、定义自己模型文件3、训练模型4、参考文献 前言 本文主要介绍如何利用YOLOv5训练自己的数据集 1、数据标注说明 以生活垃圾数据集为例子 生活垃圾数据集&#xff08;YOLO版&#xff09;点击这里直接下载本文生活垃圾数据集 生活垃圾数据集组成&…

CTF 全讲解:[SWPUCTF 2021 新生赛]jicao

文章目录 参考环境题目index.phphighlight_file()include()多次调用&#xff0c;多次执行单次调用&#xff0c;单次执行 $_POST超全局变量HackBarHackBar 插件的获取 $_POST打开 HackBar 插件通过 HackBar 插件发起 POST 请求 GET 请求查询字符串超全局变量 $_GET JSONJSON 数据…