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

注意:本人编码水平很菜。算是自己的一个总结。可能会有我还没有发现的bug。如果有人发现后可以指出,不胜感激。

1.银行家算法:

我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。

为保证资金的安全,银行家规定: (1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客; (2)

顾客可以分期贷款,但贷款的总数不能超过最大需求量; (3)

当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款; (4)

当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.

操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。 ---------引用自百度百科

2.简单来说:系统中的资源是有限的。不足以一下子把所有进程所需的资源都分配。

我们需要做的就是在有限的资源下,是否有一个分配顺序,可以使得全部进程都可以获得资源并运行,如果可以则返回一个安全队列,如果不可以,则说明有风险,系统可能会陷入死锁。

3.数据结构

1)可利用资源向量Available

是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。

2)最大需求矩阵Max

这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。

3)分配矩阵Allocation

这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的

数目为K。 4)需求矩阵Need。

这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。

4.举个例子:

系统总资源是(9,3,6)

max Allocation need Available finished
R1 R2 R3 R1 R2 R3 R1 R2 R3 R1 R2 R3
p1 3 , 2 , 2 1 ,0 ,0 2 , 2 , 2 6,1,4 (9,3,6) True
p2 6 ,1 ,3 5 ,1 ,2 1 , 0 ,1 0,1,0 (6,2,3) True
p3 3 ,1 ,4 2 , 1 , 1 1 ,0 , 3 5,2,0 (8,3,4) Ture
p4 4 ,2 , 2 0 ,0, 2 4 ,2 ,0 4,1,4 (8,3,6) True

分配给p2(1,0,1) 目前系统可用资源 1,1,1

1.此时p2仍然需要1,0,1 ,可以满足p2所需资源 。p2完成后释放资源

此时系统资源总数为(6,2,3)

2.分配给p3,系统资源剩(5,2,0)。p3完成后释放资源,

此时的资源总数为(8,3,4)

3.分配给p4,系统资源剩(4,1,4)。P4完成后释放资源,此时系统资源总数为(8,3,6)

4.分配给p1,系统资源(6,1,4),p1完成后释放资源,此时系统资源总数为(9,3,6)

全部进程执行完毕。

安全序列为:p2---->p3--->p4---->p1

运行截图 :

5.代码段

#include<stdio.h>
#include<stdlib.h> #define Num_Dev 3 // 每个进程所需的设备的种类数量
#define Max 10 //可容纳的最多的进程数量 int Max_Need_Dev [Max][Num_Dev]; //所有进程所需要的设备的最大数目
int Allocation_Dev [Max][Num_Dev]; //所有进程已经分配到的设备的数目
int Need_Dev [Max][Num_Dev]; //所有进程还需要的设备的数目 int current_Available_Dev[Max][Num_Dev]; //记录分配完之后,此时系统的可用资源数目(因为假如会产生安全队列,那么有多少个进程就会产生多少次这样的当前分配后的可用资源数目)
int current_recycle_Dev[Max][Num_Dev]; //记录回收完之后,系统中各个设备的数目 int system_Dev[Num_Dev]; //系统中所拥有的各类设备的数量
int Available_Dev [Num_Dev]; //系统中剩余的资源数量
int finish [Max]; //存存放所有进程是否已经运行完毕。 int quene[Max]; //假设不会出现死锁,那么用于存放安全队列。 即记录每个进程的下表。 int num; // 进程的名字 void init(){
printf("请输入系统中各类资源的数目总和:\n");
for (int i = 0; i < Num_Dev; i++)
{
scanf("%d",&system_Dev[i]);
Available_Dev[i] = system_Dev[i];
printf("%d\t",Available_Dev[i]);
} printf("\n"); printf("请输入进程的数量:\n");
scanf("%d",&num);
printf("\n"); printf("请输入各个进程运行所需要全部设备的数量:\n");
for(int i = 0;i < num; i ++){
for (int j = 0; j < Num_Dev; j++)
{
scanf("%d",&Max_Need_Dev[i][j]);
}
}
printf("\n"); printf("请输入各个进程已经分配到的设备的数目:\n");
for(int i = 0;i < num; i ++){
for (int j = 0; j < Num_Dev; j++)
{
scanf("%d",&Allocation_Dev[i][j]);
Available_Dev[j] = Available_Dev[j] - Allocation_Dev[i][j]; //计算系统中剩余设备的数目
}
} printf("\n");
for(int i = 0;i < num; i ++){
for (int j = 0; j < Num_Dev; j++)
{
Need_Dev[i][j] = Max_Need_Dev[i][j] - Allocation_Dev[i][j]; //计算各个进程依然所需要的各个设备的数目
}
}
for (int i = 0; i < num; i++)
{
finish[i] = 0;
quene[i] = -1;
} }
void print(){
printf("进程ID\t|\tMax\t|\tAllocat\t|\tNeed\t|\tAvail\t|\t\tfinish\n");
for (int i = 0; i < num; i++)
{
printf("%d\t|\t",quene[i]);
printf("%d,%d%,%d\t|\t%d,%d%,%d\t|\t%d,%d%,%d\t|\t%d,%d%,%d (%d,%d,%d)\t|\t%d\\",Max_Need_Dev[i][0],Max_Need_Dev[i][1],Max_Need_Dev[i][2],Allocation_Dev[i][0],Allocation_Dev[i][1],Allocation_Dev[i][2],Need_Dev[i][0],Need_Dev[i][1],Need_Dev[i][2],current_Available_Dev[i][0],current_Available_Dev[i][1],current_Available_Dev[i][2],current_recycle_Dev[i][0],current_recycle_Dev[i][1],current_recycle_Dev[i][2],finish[i]);
printf("\n");
}
} int conpare(int *p){ //判断当前可用设备的数目是否可以满足所传入的进程的要求
for(int j = 0;j < Num_Dev; j ++){
if(*(p+j) > Available_Dev[j] ){
return 0;
}
}
return 1;
} void recycle(int *p){ //若一个进程运行完毕,回收已经分配给它的设备
for (int i = 0; i < Num_Dev; i++)
{
Available_Dev[i] += *(p+i);
}
} int allocation(){
int flag = 0;
int count = 1; //判断死锁。就是遍历一遍之后没有进程可以运行。
int i = 0; //判断是哪一个进程
int index = 0; //用于记录安全队列的下表
int max_times; //因为有num个变量, 所以假如有安全队列,最多就是寻找num的平方次
while (1)
{
max_times ++;
if(conpare(Need_Dev[i])==1&&finish[i] == 0){
count = 0;
finish[i] = 1; //表示该进程获得资源后运行完毕
for (int j = 0; j < Num_Dev; j++) // 让进程获取剩余设备 即
{
Allocation_Dev[i][j] += Need_Dev[i][j]; //1.让进程已经分配的设备数目加上它仍然需要的
Available_Dev[j] -= Need_Dev[i][j]; //2.系统中目前可用的设备数目减去进程需要的 current_Available_Dev[i][j] = Available_Dev[j]; //记录分配完之后,此时系统的可用资源数目(因为假如会产生安全队列,那么有多少个进程就会产生多少次这样的当前分配后的可用资源数目)
} recycle(Max_Need_Dev[i]); // 回收资源
for (int j = 0; j < Num_Dev; j++)
{
current_recycle_Dev[i][j] += Available_Dev[j];
} quene[index] = i;
index ++;
if(index == num ){
flag = 1;
printf("安全队列已经返回了。快去看看吧!\n");
break;
}
}
if(count == num){
printf("会发生死锁。无安全队列。。。。。。\n");
break;
}
if(i == num - 1){
i = 0;
continue;
}
if(max_times == num*num){
printf("全部可能已经执行完毕,无安全队列。。。。。。\n");
break;
}
count ++;
i ++;
}
return flag;
} int main(void ){
init();
int flag = allocation();
print();
if(flag == 1){
for (int i = 0; i < num; i++)
{
printf("%d--->",quene[i]);
} }
printf("\n");
system("pause");
}

【操作系统】银行家算法实现(C语言)的更多相关文章

  1. C语言实现 操作系统 银行家算法

    /**************************************************** 银行家算法 算法思想: 1. 在多个进程中,挑选资源需求最小的进程Pmin. 可能存在多类资 ...

  2. 操作系统——银行家算法(Banker's Algorithm)

    之前写过一篇关于死锁和银行家算法的详细描述的博客https://www.cnblogs.com/wkfvawl/p/11598647.html 写这篇博客的目的,主要是详细讲解一下银行家算法以及代码的 ...

  3. 操作系统,银行家算法模拟实现(Windows 环境 C++)

    计算机操作系统课设需要,写了两个下午的银行家算法(陷在bug里出不来耽误了很多时间),参考计算机操作系统(汤子瀛) 实现过程中不涉及难度较大的算法,仅根据银行家算法的思想和步骤进行实现.以下为详细步骤 ...

  4. python模拟银行家算法

    前言: 大二第一学期学习了操作系统,期末实验课题要求模拟算法.遂根据自己学习的python写下此文.以此锻炼自己编码能力.虽说是重复造轮子,但还是自己的思路体现 代码及注释如下(银行家算法不再赘述): ...

  5. 预防和避免死锁的方法及银行家算法的java简单实现

    预防死锁 (1) 摒弃"请求和保持"条件 基本思想:规定所有进程在开始运行之前,要么获得所需的所有资源,要么一个都不分配给它,直到所需资源全部满足才一次性分配给它. 优点:简单.易 ...

  6. C程序模拟实现银行家算法

    C程序模拟实现银行家算法 上周又做操作系统实验,题目是用程序模拟实现银行家算法,写了半天还真有点晕,主要是因为想尽可能符合课本上的描述,所以写出来的程序就比较恶心了,好了,银行家算法就不多说了,不了解 ...

  7. 银行家算法之JavaScript实现

    上学期有个课程叫做操作系统,期末的时候这课程还有个课程设计,其中有个题目叫做银行家算法. 什么是银行家算法我就不解释了! 看着同学们的设计,大同小异甚至前篇一律. 清一色的控制台程序,清一色的蛋疼输入 ...

  8. java面试题之死锁产生的条件,以及如何避免死锁,银行家算法,产生死锁后如何解决(阿里面试题)

    死锁产生的四个必要条件: 互斥:一个资源每次只能被一个进程使用(资源独立) 请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放(不释放锁) 不剥夺:进程已获得的资源,在未使用之前,不能强行 ...

  9. C# Math.Round()的银行家算法

    可能很多人都跟我一样,都只知道Math.Round()是C#中用来做四舍五入,保留指定小数位的 但实际上它并不是真正的四舍五入,而是银行家算法的四舍六入五取偶 事实上这也是IEEE的规范,因此所有符合 ...

随机推荐

  1. AtCoder Beginner Contest 181 题解

    总结 第一次 \(AK\ ABC\) 的比赛,发一个截图纪念一下 A - Heavy Rotation 题目大意 一个人一开始穿白衣服,一天后换成黑衣服,再过一天又换成白衣服,问第 \(n(n \le ...

  2. JavaMail 发送邮件出现 Connection reset 问题

    问题描述 使用 java mail 发送邮件的时候,申请的 163 邮箱作为发件箱,然无论如何配置,均出现 Connection reset,无法正常发送邮件. Exception in thread ...

  3. How to refresh datasource args caller[X++]

    To refresh  datasource args caller, you must add override method close on form like source code belo ...

  4. c++11-17 模板核心知识(一)—— 函数模板

    1.1 定义函数模板 1.2 使用函数模板 1.3 两阶段翻译 Two-Phase Translation 1.3.1 模板的编译和链接问题 1.4 多模板参数 1.4.1 引入额外模板参数作为返回值 ...

  5. Python替换字符串中的空格

    这是来源剑指offer的第二题,直接调用replace函数进行空格替换即可. 当我又想试试挨个字符比较进行替换时程序报错了: 错误原因是在python中字符串是一个不可变的数据类型,如果进行替换字符可 ...

  6. 小学生学习C++应该具备哪些基础?

    一.电脑操作基础: 应该具备一些必要的电脑相关的知识,如操作系统的相关知识,如何打开.编辑.保存文件.对电脑的能力有一些基本的认识,以及会使用鼠标,键盘熟练输入. 磨刀不误砍柴工,至少要做到能快速找到 ...

  7. 解决无法访问 Github

    可以正常使用Google,但无法打开Github. 查阅了一些资料,发现需要在hosts文件中添加映射. 在hosts文件中加入两行 140.82.113.4 github.com 140.82.11 ...

  8. Serilog 源码解析——数据的保存(上)

    在上一篇中,我们主要研究了Serilog是如何解析字符串模板的,它只是单独对字符串模板的处理,对于日志记录时所附带的数据没有做任何的操作.在本篇中,我们着重研究日志数据的存储方式.(系列目录) 本篇所 ...

  9. Redis 数据结构之字符串的那些骚操作

    Redis 字符串底层用的是 sds 结构,该结构同 c 语言的字符串相比,其优点是可以节省内存分配的次数,还可以... 这样写是不是读起来很无聊?这些都是别人咀嚼过后,经过一轮两轮三轮的再次咀嚼,吐 ...

  10. Kafka 消费者及消费者分区策略

    消费方式: consumer 采用 pull(拉)模式从 broker 中读取数据. push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的. 它的目标是尽可能以最 ...