银行家算法 源码+实验报告(用了自取)

news2024/11/16 21:54:27

XI`AN TECHNOLOGICAL UNIVERSITY

课程设计报告

实验课程名称 操作系统—银行家算法    

专    业:计算机科学与技术         

班    级:               

姓    名:                  

学    号:         

实验学时:                        

指导教师:                    

成    绩:                         

        

    2022      12    25

                       目   录

中文摘要..................................................................................................................................

英文摘要..................................................................................................................................

主要符号表............................................................................................................................ 1

1 绪论......................................................................................................................................

1.1 综述............................................................................................................................ 1

1.2 产生死锁的原因及必要条件......................................................................................

1.2.1 产生死锁的原因.............................................................................................. 2

1.2.2 产生死锁的必要条件......................................................................................

1.3 处理死锁的基本方法................................................................................................ 2

1.4 本文主要研究内容......................................................................................................

2 银行家算法的研究............................................................................................................ 3

2.1 系统安全状态..............................................................................................................

2.1.1 安全状态.......................................................................................................... 6

2.1.2 安全状态之例..................................................................................................

2.1.3 由安全状态向不安全状态的转换.................................................................. 7

2.2 利用银行家算法避免死锁..................................................................................

2.2.1 银行家算法中的数据结构.............................................................................. 9

2.2.2 银行家算法......................................................................................................

2.2.3 安全性算法.................................................................................................... 10

    2.3 银行家算法用例.........................................................................................................

3 需求分析..............................................................................................................................

4 逻辑设计..............................................................

4.1 实验原理..........................................................

4.2 基本技术路线图....................................................

4.3 程序流程图......................................................................................................................

5 系统设计..............................................................

5.1 数据结构定义...................................................... 1

5.2 主要变量..........................................................

5.3 定义函数.......................................................... 2

6 测试与分析............................................................

6.1 实验过程原始记录................................................. 2

6.2 出错问题举例...................................................... 3

7 程序运行..............................................................

7.1 程序运行截图......................................................

7.2 实验结果.......................................................... 7

8 结论..................................................................

         

                  银行家算法

银行家算法是操作系统的经典算法之一,用于避免死锁情况的出现。

它最初是为银行设计的(因此得名),通过判断借贷是否安全,然后决定借不借。

在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。

用在操作系统中,银行家、出借资金、客户,就分别对应操作系统、资源、申请资源的进程。

每一个新进程进入系统时,必须声明需要每种资源的最大数目,其数目不能超过系统所拥有的的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程,若有,再进一步计算在将这些资源分配给进程后,是否会使系统处于不安全状态如果不会才将资源分配给它,否则让进程等待。

                  Banker Algorithm

Banker algorithm is one of the classical algorithms of operating system, which is used to avoid deadlock.

It was originally designed for banks (hence its name), by judging whether borrowing is safe, and then deciding whether to borrow or not.

In the bank, the number of customers applying for loans is limited. Each customer should declare the maximum amount of funds needed to complete the project when applying for loans for the first time. When all loan requirements are met, the customer should return the money in time. Bankers should try their best to meet customers' needs when the number of loans they apply for does not exceed their own maximum.

When used in the operating system, bankers, loan funds, and customers correspond to the operating system, resources, and resource application processes respectively.

When each new process enters the system, it must declare the maximum number of each resource required, which cannot exceed the total resources owned by the system. When a process requests a group of resources, the system must first determine whether there are enough resources allocated to the process. If so, it will further calculate whether the system will be in an unsafe state after these resources are allocated to the process. If not, the system will allocate resources to it. Otherwise, the process will wait.

1.绪论

1.1综述

银行家算法是操作系统的经典算法之一,用于避免死锁情况的出现。所以前情提要我们先了解关于死锁的知识,我们需要了解有关死锁的原因及必要条件、如何处理死锁。

由此以死锁为切入口进行编写我们的银行家算法。

1.2 产生死锁的原因及必要条件

   1.2.1 产生死锁的原因

     死锁指的是并发进程彼此互相等待对方所拥有的资源,并且这些并发进程在得到对方的资源之前不会释放自己所拥有的资源,若无外力作用,它们都将无法推进下去。这些永远在互相等待的进程称为死锁进程。

      

1.2.2 产生死锁的必要条件

(1)互斥条件:并发进程所要求和占有的资源是不能同时被两个以上进程使用或操作的,进程对他所需要的资源进行排他性控制。

(2)不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行剥夺,而且只能由获得该资源的进程自己释放。

(3)请求和保持条件:进程已经至少保持了一个资源,但又提出新的资源请求,而该资源已被其他进程占有,此时请求进程阻塞,但对自己已获得的资源保持不放。

(4)循环等待条件:存在一种进程资源等待链,链中每一个进程已获得资源同时被链中的下一个进程所请求。

只要有一个条件不满足,死锁就可解除。

1.3 处理死锁的基本方法

死锁处理策略如下

(1)预防死锁:破坏死锁产生的四个必要条件之一。

(2)避免死锁:用某种方法防止系统进入不安全状态,从而避免死锁。

(3)死锁的检测和解除:允许死锁发生,操作系统会负责检测出死锁的发生,然后采取某种措施去解除死锁。

1.4 本文主要研究内容

       本文是初步了解有关死锁方面的基础知识。对于 银行家算法的前情提要有了一定基础。

2.银行家算法的研究

       2.1系统安全状态

      2.1.1安全状态

系统能够按照某种推进顺序,为每个进程p分配其所需的资源,直至满足每个进程对资源的最大需求,进而使每个进程都可以顺利完成的一种系统状态。

检查当前剩余可用资源是否能满足某个进程的最大需求,如果可以,就把该进程加入安全序列,并把该进程持有的资源全部回收。不断重复上述过程,看最终是否能让所有进程都进入安全序列。

   2.1.2安全状态之例

经分析发现,在 T0 时刻系统是安全的,因为这时存在一个安全序列〈P2,P1,P3〉,即只要系统按此进程序列分配资源,就能使每个进程都顺利完成。例如,将剩余的磁带机取 2台分配给 P2,使之继续运行,待 P2完成,便可释放出 4 台磁带机,于是可用资源增至 5 台;以后再将这些全部分配给进程 P1,使之运行,待 P1 完成后,将释放出 10 台磁带机,P3 便能获得足够的资源,从而使 P1、P2、P3每个进程都能顺利完成。

2.1.3由安全状态向不安全状态的转换

如果不按照安全序列分配资源,则系统可能会由安全状态进入不安全状态。例如,在T0 时刻以后,P3又请求 1 台磁带机,若此时系统把剩余 3 台中的 1 台分配给 P3,则系统便进入不安全状态。因为此时也无法再找到一个安全序列,例如,把其余的 2 台分配给 P2,这样,在 P2完成后只能释放出 4 台,既不能满足 P1尚需 5 台的要求,也不能满足 P3尚需 6台的要求,致使它们都无法推进到完成,彼此都在等待对方释放资源,即陷入僵局,结果导致死锁。类似地,如果我们将剩余的 2 台磁带机先分配给 P1或 P3,也同样都无法使它们推进到完成,因此,从给 P3分配了第 3 台磁带机开始,系统便又进入了不安全状态。由此可见,在 P3请求资源时,尽管系统中尚有可用的磁带机,但却不能分配给它,必须让 P3一直等待到 P1和 P2完成,释放出资源后再将足够的资源分配给 P3,它才能顺利完成。

2.2利用银行家算法避免死锁

最有代表性的避免死锁的算法,是 Dijkstra 的银行家算法。这是由于该算法能用于银行系统现金贷款的发放而得名的。为实现银行家算法,系统中必须设置若干数据结构

2.2.1 银行家算法中的数据结构9

可利用资源向量 Available。这是一个含有 m 个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果 Available[j]=K,则表示系统中现有 R j类资源K 个。

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

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

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

2.2.2银行家算法

设 Request i是进程 Pi的请求向量,如果 Request i[j]=K,表示进程 P i需要 K 个 R j类型的资源。当 P i发出资源请求后,系统按下述步骤进行检查:

  • 如果 Request i[j]≤Need[i,j],便转向步骤(2);否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
  • 如果 Requesti[j]≤Available[j],便转向步骤(3);否则,表示尚无足够资源,Pi 须等待。
  • 系统试探着把资源分配给进程 P i,并修改下面数据结构中的数值:

  • 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程 Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程 Pi等待。

2.2.3 安全性算法

系统所执行的安全性算法可描述如下:
(1)设置两个向量:

① 工作向量 Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有 m个元素,在执行安全算法开始时,Work:=Available。

② Finish,它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i]:=false;当有足够资源分配给进程时,再令 Finish[i]:=true。

(2)从进程集合中找到一个能满足下述条件的进程:

① Finish[i]=false;

② Need[i,j]≤Work[j];若找到,执行步骤(3),否则,执行步骤(4)。

(3)当进程 Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

(4)如果所有进程的 Finish[i]=true 都满足,则表示系统处于安全状态;否则,系统处于不安全状态。

假定系统中有五个进程{P0,P1,P2,P3,P4}和三类资源{A,B,C},各种资源的数量分别为 10、5、7,在 T0时刻的资源分配情况如下图所示。

T0时刻的资源分配表

(1) T0时刻的安全性:利用安全性算法对 T0时刻的资源分配情况进行分析(下图所示)可知,在 T0时刻存在着一个安全序列{P1,P3,P4,P2,P0},故系统是安全的。

T0时刻的安全序列

(2)P1请求资源:P1发出请求向量 Request1(1,0,2),系统按银行家算法进行检查:

① Request1(1,0,2)≤Need1(1,2,2)

② Request1(1,0,2)≤Available1(3,3,2)

③ 系统先假定可为 P1分配资源,并修改 Available,Allocation1和 Need1向量,由此形成的资源变化情况如上上图中的圆括号所示。

④ 再利用安全性算法检查此时系统是否安全。如下图所示。

P1申请资源时的安全性检查

由所进行的安全性检查得知,可以找到一个安全序列{P1,P3,P4,P2,P0}。因此,系统是安全的,可以立即将 P1所申请的资源分配给它。

(3)P4请求资源:P4发出请求向量 Request4(3,3,0),系统按银行家算法进行检查:

① Request4(3,3,0)≤Need4(4,3,1);

② Request4(3,3,0)≤Available(2,3,0),让 P4等待。

(4) P0请求资源:P0发出请求向量 Requst0(0,2,0),系统按银行家算法进行检查:

① Request0(0,2,0)≤Need0(7,4,3);

② Request0(0,2,0)≤Available(2,3,0);

③ 系统暂时先假定可为 P0分配资源,并修改有关数据,如下图所示。

为 P0分配资源后的有关资源数据

(5) 进行安全性检查:可用资源 Available(2,1,0)已不能满足任何进程的需要,故系统进入不安全状态,此时系统不分配资源。

3 需求分析

       (1)问题分析:银行家算法是避免死锁的算法,它是在系统进行资源分配之前,计算此次分配后状态的安全性。若此次分配后的状态是安全状态,则将资源分配给进程,若不是安全状态则令进程等待。

(2)功能要求:有录入界面,动态录入进程数、资源种类数、各类资源总数、T0时刻各进程的最大需求数、已分配数等信息;

    有算法选择界面,能够进行安全性检测、对进程动态请求资源的银行家算法检查、退出等的功能选择,要求可以进行多进程多次的资源请求;

    有输出界面,要求能够输出安全性检测的结果、如安全能够输出安全序列、能够输出进程请求资源后是否分配的结果,若不能分配要输出原因,如果能够分配,要输出分配后进程及资源的状态。

(3)输入的形式和输入值的范围:

输入的进程个数和资源种类数位整型数字;

输入的资源总数,各进程对各资源的最大需求以及各进程已经占有的各资源数目以矩阵形式输入,输入值也为整数。

(4)输出的形式:安全序列按顺序输出,系统剩余资源,各进程对各资源的需求情况用矩阵输出。

4 逻辑设计

4.1 实验原理

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

不安全状态:不存在一个安全序列。不安全状态不一定导致死锁。

安全序列:一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。银行家算法中的主要思想:在任何时刻保证至少有一个进程能得到所需的全部资源而执行到结束。

银行家算法通过动态地检测系统中资源分配情况和进程对资源的需求情况来决定如何分配资源,并能在确保系统处于安全状态时才把资源分配给申请者,从而避免系统发生死锁。

4.2 程序流程图

5 系统设计

    5.1数据结构定义

      5.2主要变量

Flag标志位变量

      5.3定义函数

对数据进行初始化,当录入进程个数m和资源种类个数n之后

分别对其Available矩阵、Max矩阵、Allocation矩阵、Need矩阵分别进行初始化

接下来就是对安全性算法的实现:

首先对于Work 向量、与Finish向量进行初始化,在一个大循环条件(所有的Finish状态位不都是True状态下进入循环)接着通过一个for循环遍历每一个进程,当该进程满足Finish状态位为false并且当前进程的Work小于等于Need条件下进行标志位Finish的更改、安全序列的录入,以及资源的回收,最终跳出while循环时,如果安全序列进程个数等于进程个数,那么此时刻系统就是安全的,并输出安全序列,否则输出系统此时刻不安全

用于判断Need不大于Work的函数

用于判断所有的Finish标志位不都是true的函数

用于回收资源的函数

下来就是银行家算法:

进入程序 首先录入需要进行资源申请的进程ID,已经需要申请的Request资源向量

进行判断Request不大于Need

进行判断Request不大于Available系统已拥有资源个数:

进行试分配:

试分配之后判断分配后是否处于安全序列

6 测试与分析

      6.1实验过程原始记录

// 进程个数 5

// 资源种类 3

// 进程名称'p0', 'p1','p2','p3','p4'

// 资源名称 'A','B','C'

// 可利用资源向量  3 3 2

// 每个进程所需要分配的每类最大资源情况  753 322 902 222 433

// 系统中已分配资源情况                010 200 302 211 002

    6.2 出错问题举例

对于Need为零时,没有对矩阵进行更新,应该对资源分配后的矩阵进行判断,将Allocation矩阵进行置空,我错理解为置为与Max矩阵相同的做法,Need为零,说明该进程已经满足了各类资源的所有请求,均达到了Max所最大需要的资源,这时候系统就会将该进程所占据的进程资源进行释放,所有此时该进行所拥有的系统资源就会进行释放,Allocation矩阵就应置空。

对于安全性算法flag标志位的设立,初始时,采用了n个进程相互独立检测,并没有掌握其进入安全序列后对其是否继续执行,加入了flag判断后,可以根据flag标志位的前后判断来得出本次查找是否得到至少一个序列。

7 程序运行

       7.1 程序运行截图

      7.2 实验结果

对于书上的例子成功地计算出了安全序列,根据银行家算法的原理,初始化时要保证进程最大需求量不超过系统每类资源总数量,分配的资源不超过进程的最大需求量,要保证至少一个进程能够得到资源执行结束。当可用资源不足以满足进程运行时,不分配资源,避免死锁。

设计的数值范围会影响到出现不安全情况的概率。如果设计的系统总资源少时,进程对资源的申请会更加难以得到满足,所以出现不安全的概率会提高,同样,设计的进程最大需求量大时,各个进程对资源的需求相应变多,更加容易不安全,还有系统已分配资源的范围,如果已分配的资源越多,剩下可用的资源就越少,也容易导致不安全。可以通过调高系统每类资源总数量的范围、降低进程最大需求量和已分配资源的范围降低出现不安全的概率。

8 结论

此次实验总体并不难,利用C语言实现的同时,在每次进程申请时都要判断其是否满足释放资源条件,满足则释放,释放后需要检测阻塞队列,将队列中每个满足的进程都转为就绪态,其中阻塞队列中使用了一个简单的排序算法,方便进行进程调度。以下是对知识点的总结:

1.银行家算法是一种用来避免操作系统死锁出现的有效算法。

2.死锁:是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

3.死锁的发生必须具备以下四个必要条件:

1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

3)不抢占条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

4)循环等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

4.银行家算法是避免死锁的一种重要方法,防止死锁的机构只能确保上述四个条件之一不出现,则系统就不会发生死锁。

5.为实现银行家算法,系统必须设置若干数据结构,同时要解释银行家算法,必须先解释操作系统安全状态和不安全状态。

6.安全序列:是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。

7.安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。

8.安全状态一定是没有死锁发生。不安全状态:不存在一个安全序列。不安全状态不一定导致死锁

#if 0

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;

// #define PROCESSNAME 3 // 进程名称长度
int m = 100;  // 资源种类 3 // 资源名称 
int n = 100;  // 进程个数 5

// char ProcessNum[n] = { 'p0', 'p1','p2','p3','p4' };
// char ProcessName[PROCESSNAME] = { 0 };
char SoreceKind[100] = { 'A','B','C','D','E','F','G','H','I','J' };
int ProcessNum[100] = { 0,1,2,3,4,5,6,7,8,9,10 };
int Available[100] = { 0 };			// 可利用资源向量  3 3 2
int Max[100][100] = { 0 };			// 每个进程所需要分配的每类最大资源情况  753 322 902 222 433
int Allocation[100][100] = { 0 };	// 系统中已分配资源情况					 010 200 302 211 002
int Need[100][100] = { 0 };
int Work[100] = { 0 };
int Finish[100] = { 0 };
int _get[100] = { 0 };
int Request[100] = { 0 };

int _Available[100] = { 0 };
int _Allocation[100][100] = { 0 };
int _Need[100][100] = { 0 };

void InitNeed()
{
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < m; ++j)
		{
			Need[i][j] = Max[i][j] - Allocation[i][j];
		}
	}
}

void InitCurrentAvailable()
{
	cout << "请分别输入各类可利用资源情况->" << endl;
	for (int i = 0; i < m; i++)
	{
		scanf_s("%d", &Available[i]);
	}
	cout << "初始化Available数组完成" << endl;
	return;
}

void InitCurrentMax()
{
	cout << "请分别输入系统中每个进程所需要分配的每类最大资源情况->" << endl;
	for (int i = 0; i < n; i++)
	{
		cout << "请输入第p" << i << "个进程的最大资源分配情况" << endl;
		for (int j = 0; j < m; j++)
		{
			scanf_s("%d", &Max[i][j]);
		}
	}
	cout << "初始化Max数组完成" << endl;
	return;
}
void InitCurrentAllocation()
{
	cout << "请分别输入系统中已分配资源情况->" << endl;
	for (int i = 0; i < n; i++)
	{
		cout << "请输入第p" << i << "个进程的各类资源分配情况" << endl;
		for (int j = 0; j < m; j++)
		{
			scanf_s("%d", &Allocation[i][j]);
		}
	}
	cout << "初始化Allocation数组完成" << endl;
	return;
}

void Print()
{
	int i, j;
	cout << "当前资源分配如下:" << endl;
	cout << "已拥有各类资源情况:" << endl;
	for (int i = 0; i < m; i++)
		cout << SoreceKind[i] << " ";
	cout << endl;
	for (int i = 0; i < m; i++)
		cout << Available[i] << " ";
	cout << endl;
	printf("	    Max    Allocation    Need\n");
	printf("进程名     ");
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < m; j++)
		{
			cout << SoreceKind[j] << " ";
		}
		cout << "     ";
	}
	cout << endl;
	for (i = 0; i < n; i++)
	{
		cout << "  P" << ProcessNum[i] << "	  ";
		for (j = 0; j < m; j++)
			cout << " " << Max[i][j];
		cout << "     ";
		for (j = 0; j < m; j++)
			cout << " " << Allocation[i][j];
		cout << "     ";
		for (j = 0; j < m; j++)
			cout << " " << Need[i][j];
		cout << endl;
	}
}

void Init()
{
	int choice = 0;
	int M, N;
	cout << "请输入进程个数和资源种类" << endl;
	scanf_s("%d %d", &N, &M);
	m = M;
	n = N;
	InitCurrentAvailable();
	InitCurrentMax();
	InitCurrentAllocation();
	InitNeed();
	Print();
}


bool Exectuable(int i, int Work[])	// 如果满足一个进程的每一项资源(A、B、C) 就返回TRUE
{
	for (int j = 0; j < m; j++)
	{
		if (Need[i][j] > Work[j])
		{
			return false;
		}
	}
	return true;
}

void Security_recycling(int Work[], int i)
{
	for (int j = 0; j < m; j++)
	{
		Work[j] = Work[j] + Allocation[i][j];
	}
}

bool Finish_Security(int Finish[])
{
	for (int i = 0; i < n; i++)
	{
		if (Finish[i] == 0)
			return false;		// 如果为Finish[i] 为假,那么 !Sercurity即为真
	}
	return true;
}

bool SecurityAlgorithm()
{
	int a = 0, flag = 1;
	memcpy(Work, Available, m * sizeof(int));
	memset(Finish, 0, n * sizeof(int));
	while (!Finish_Security(Finish) && flag)
	{
				flag = 0;	// flag用来判断本轮产生一个安全序列
		for (int i = 0; i < n; i++)
		{
			if (Finish[i] == 0 && Exectuable(i, Work))
			{
				_get[a++] = i;		// 将进程序列存入get数组中
				Finish[i] = 1;		// 将该进行的Finish标志向量位置为TRUE
				Security_recycling(Work, i);	// 资源回收 将进程完成后释放的资源 放入 可利用资源Work向量中
				flag = 1;	// 如果flag发生变化,则说明产生一个
			}
		}
	}
	if (a != n)
	{
		cout << "该系统是不安全的,因为不存在任何一个安全序列" << endl;
		return false;
	}
	else
	{
		cout << "该时刻此系统是安全的,因为该时刻存在一个安全序列:";
		for (int i = 0; i < n; i++)
			cout << " p" << _get[i];
		cout << endl;
		return true;
	}
}


bool NotGreaterThanNeed(int RequestID)
{
	for (int i = 0; i < m; i++)
	{
		if (Request[i] > Need[RequestID][i])
			return false;
	}
	return true;
}

bool NotGreaterThanAvailable(int RequestID)
{
	for (int i = 0; i < m; i++)
	{
		if (Request[i] > Available[i])
			return false;
	}
	return true;
}

void TrialAllocation(int RequestID)
{
	memcpy(_Available, Available, m * sizeof(int));
	memcpy(_Allocation, Allocation, m * n * sizeof(int));
	memcpy(_Need, Need, m * n * sizeof(int));
	for (int i = 0; i < m; i++)
	{
		Available[i] -= Request[i];
		Allocation[RequestID][i] += Request[i];
		Need[RequestID][i] -= Request[i];
	}
}

void Recovery(int RequestID)
{
	/*for (int i = 0; i < m; i++)
	{
		Available[i] += Request[i];
		Allocation[RequestID][i] -= Request[i];
		Need[RequestID][i] += Request[i];
	}*/
	memcpy(Available, _Available, m * sizeof(int));
	memcpy(Allocation, _Allocation, m * n * sizeof(int));
	memcpy(Need, _Need, m * n * sizeof(int));
	cout << "恢复成功" << endl;
}

bool NeedToNULL(int RequestID)
{
	for (int i = 0; i < m; i++)
	{
		if (Need[RequestID][i] != 0)
			return false;
	}
	return true;
}

void ReturnZero_Resource_recovery(int RequestID)
{
	if (NeedToNULL(RequestID))
	{
		for (int i = 0; i < m; i++)
		{
			Available[i] += Allocation[RequestID][i];
			Allocation[RequestID][i] = 0;
		}
	}
	Print();
}

void BankerAlgorithm()
{
	// 0、判断t0时刻的安全性
	if (SecurityAlgorithm())
	{
		// 我们需要初始化一个请求向量
		int RequestID;
		cout << "请输入RequestID" << endl;
		cin >> RequestID;
		cout << "请输入Request" << endl;
		for (int i = 0; i < m; i++)
		{
			scanf_s("%d", &Request[i]);
		}
		// 1、判断Request向量中各类资源是否满足第ID个进程的Need需求
		//    请求不能大于Need
		if (NotGreaterThanNeed(RequestID))
		{
			// 2、请求不能超过系统所能提供的资源
			if (NotGreaterThanAvailable(RequestID))
			{
				// 3、进行试分配
				TrialAllocation(RequestID);
				// 4、进行判断是否分配后处于安全序列
				if (SecurityAlgorithm())
				{
					cout << "那么系统正式将资源分配给进程P" << RequestID <<"如下为分配后结果:" << endl;
					// 5、对于Need矩阵为零的处理
					ReturnZero_Resource_recovery(RequestID);
				}
				else
				{
					// 不满足安全性检测 调用恢复函数
					Recovery(RequestID);
					cout << "本次试探性分配作废,恢复原来的资源分配状态进行等待" << endl;
				}
			}
			else
				cout << "尚无足够资源,此次请求需要等待" << endl;
		}
		else
			cout << "出错!所需要的资源数以超过它所宣布的最大值" << endl;
	}
	else
		cout << "t0时刻不存在这么一个安全序列,该系统无法满足本次资源请求" << endl;
	return;
}

void menu2()
{
	cout << "********************************" << endl;
	cout << "     1——资源请求" << endl;
	cout << "     0——退出返回" << endl;
	cout << "********************************" << endl;
}

void _BankerAlgorithm()
{
	int choice = 0, flag = 1;
	while (flag)
	{
		menu2();
		cout << "请输入要进行的操作->" << endl;
		cin >> choice;
		switch (choice)
		{
		case 1:
			BankerAlgorithm();
			break;
		case 0:
			flag = 0;
			break;
		default:
			cout << "输入错误,请重新输入" << endl;
			break;
		}
	}
}



void menu1()
{
	printf("********************************\n");
	printf("*****银行家算法程序设计*********\n");
	printf("     1——初始化数据\n");
	printf("     2——银行家算法\n");
	printf("     3——安全性算法(t0时刻)\n");
	printf("     0——演示完成退出程序\n");
	printf("********************************\n");
}
int main()
{
	int choice = 0;
	while (1)
	{
		menu1();
		cout << "请输入要进行的操作->" << endl;
		cin >> choice;
		switch (choice)
		{
		case 1:
			Init();
			break;
		case 2:
			_BankerAlgorithm();
			break;
		case 3:
			SecurityAlgorithm();
			break;
		case 0:
			exit(0);
			break;
		default:
			cout << "输入错误,请重新输入" << endl;
			break;
		}
	}
	return 0;
}
#endif

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

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

相关文章

小程序03/ uni-app自定义全局组件 、 uni-app项目引入 Uview-ui 框架教程方法 和 Uview框架介绍

一. uni-app自定义全局组件 1.创建组件 注意: 在components文件夹下创建组件 、文件夹名要与文件名保持一致 2.使用组件 注意: 在pages文件夹下任意vue文件、 template标签内使用该组件即可 二.uni-app项目引入Uview-ui框架教程方法 和 Uview框架介绍 (1) Uview介绍: Uvi…

【自学Java】Java运算符

Java运算符 Java运算符 Java 程序是由许多语句组成的&#xff0c;而语句的基本操作单位是表达式与运算符。运算符就是数学中的运算符号&#xff0c;如 、-、*、 / 等等。 Java 中提供了许多的运算符&#xff0c;这些运算除了可以处理一般的数学运算外&#xff0c;还可以处理…

Android---AndroidX

目录 Android 支持库 Android Support Library AndroidX 如何迁移老项目到 AndroidX? 支持库的作用 Android 支持库 Android 支持库是每个Android 应用程序中必不可少的一部分&#xff0c;你会发现它们无处不在。支持库为开发人员提供了将 Android 的最新和最强大功能添加…

《最重要的事,只有一件》笔记——目标不是做得更多,而是让自己需要的事情更少

目录 一、引言 二、书中摘要 1、只做一件事、一次只做一件事 2、专心于一件事不那么容易 3、我们不可能同时专注于两件事 4、平衡工作与生活是无稽之谈 5、怎么做 6、成功的习惯-围绕着你的终极目标 7、找到投入的意义 8、确定优先事务-这要看你目前和将来的打算 9、…

【自然语言处理】【ChatGPT系列】FLAN:微调语言模型是Zero-Shot学习器

FLAN: 微调语言模型是Zero-Shot学习器《Finetuned Language Models are Zero-shot Learners》论文地址&#xff1a;https://arxiv.org/abs/2109.01652 相关博客 【自然语言处理】【ChatGPT系列】FLAN&#xff1a;微调语言模型是Zero-Shot学习器 【自然语言处理】【ChatGPT系列】…

R语言geodetector包基于栅格图像实现地理探测器操作

本文介绍基于R语言中的geodetector包&#xff0c;依据多张栅格图像数据&#xff0c;实现地理探测器&#xff08;Geodetector&#xff09;操作的详细方法。 需要说明的是&#xff0c;在R语言中进行地理探测器操作&#xff0c;可以分别通过geodetector包、GD包等2个包实现。其中&…

react18+eslint+prettier 配置

新建项目 create-react-app.cmd react18 --template typescript配置别名 安装 craco npm install craco/craco -D新建 craco.config.js const path require("path"); const resolve (dir) > path.resolve(__dirname, dir); module.exports {// 配置别名web…

Kubernetes:Service

文章目录1、Service 定义1.1、无选择符的服务1.2、Endpoints2、服务发布类型2.1、ClusterIP2.2、NodePort2.3、ExternalName2.4、loadbalancer3、无头服务3.1、有选择符的服务3.2、无选择符的服务4、服务发现4.1、环境变量4.2、DNS5、Service TLSService&#xff1a;将运行在一…

力扣(LeetCode)1801. 积压订单中的订单总数(C++)

优先队列模拟 根据题目描述模拟。 如果该订单是一笔采购订单 buy &#xff0c;则可以查看积压订单中价格 最低 的销售订单 sell 。提示我们&#xff0c;建立小根堆&#xff0c;维护价格最低的销售订单sell 。 反之亦然&#xff0c;如果该订单是一笔销售订单 sell &#xff0c;…

【技术分享】戴尔工作站安装Win10+Ubuntu20.04双系统教程与避坑指南

文章目录引言1.安装前的几个注意事项&#xff08;避坑指南&#xff09;1.1.有多块硬盘&#xff0c;该如何分配给Win10和Ubuntu系统&#xff1f;1.2.Ubuntu分区应该怎么分&#xff1f;2.系统安装步骤2.1.下载系统镜像2.2.制作U盘启动盘2.3.进入Win10系统分配系统空间2.4.BIOS设置…

强力推荐:关于谷歌ChatGPT模型140个示例的展示与实现功能

目录 1、ChatGPT 介绍与使用简要介绍安装ChatGPT与使用想写出有效的问答吗?使用 ChatGPT 桌面应用程序使用 prompts.chat2、ChatGPT模型140个示例充当 Linux 终端充当英语翻译和改进者担任`position`面试官充当 JavaScript 控制台充当 Excel 工作表充当英语发音帮手充当旅游指…

【C++】bitset(位图)的模拟实现

目录 一、bitset接口介绍 二、bitset的实现 1. 构造函数 2. 设置位&#xff08;set&#xff09; 3. 清空位&#xff08;reset&#xff09; 4. 获取位的状态&#xff08;test&#xff09; 三、源代码 一、bitset接口介绍 #include <iostream> #include <vecto…

Fujian Medical insurance and pension for urban and rural residents

【城乡居民医保、养老】二维码缴纳步骤&#xff0c;本文仅仅辅助需要人士&#xff0c;可忽略 第一步&#xff0c;长按二维码 第二步&#xff0c;点击【识别图中二维码】 第三步&#xff1a;个人社&#xff08;医&#xff09;保办费页面&#xff0c;点击【个人社&#xff08;医&…

一次 SQL 查询优化原理分析

一&#xff0c;前言 证实 参考资料 有一张财务流水表&#xff0c;未分库分表&#xff0c;目前的数据量为9555695&#xff0c;分页查询使用到了limit&#xff0c;优化之前的查询耗时16 s 938 ms (execution: 16 s 831 ms, fetching: 107 ms)&#xff0c;按照下文的方式调整SQL…

连接表「INNER JOIN」「LEFT JOIN」「RIGHT JOIN」+ 多表查询

目录表关联执行顺序 及 原理第一步、做笛卡尔积第二步&#xff1a;根据ON后的连接条件筛选笛卡尔积的结果第三步&#xff1a;补充左表&#xff08;LEFT JOIN&#xff09;或右表&#xff08;RIGHT JOIN&#xff09;不满足连接条件的数据&#xff08;INNER JOIN内关联时无此步骤&…

CMOS门电路总结

目录 MOS管&#xff1a; CMOS组成的常见门电路 反相器&#xff08;非门&#xff09;&#xff1a; 与非门 或非门 OD门 三态门 MOS管简介&#xff1a; > NMOS: 漏极&#xff08;D&#xff09;入&#xff0c;源极&#xff08;S&#xff09;出&#xff0c;栅极(G)加正电压…

【MyBatis】级联处理、association、collection、分布查询(详细模板,可直接套用)

目录 示例 一、处理“多对一”映射关系 1.1、级联查询 1.2、association 1.3、分步查询 二、处理“一对多”映射关系 2.1、collection 2.2、分步查询 示例 例如&#xff1a;员工与部门表 员工&#xff1a; 部门&#xff1a; 解释&#xff1a; 两张表通过dept_id联系起来…

ubuntu22.04安装MySQL、Hive及Hive连接MySQL操作

前言 这篇文章主要讲述的是ubuntu22.04上数据仓库Hive的安装和使用 正文 建议按照文章实践前稍微通读下全文 安装MySQL服务端和客户端 相关命令&#xff1a; sudo apt-get install mysql-server sudo apt-get install mysql-client 修改mysql的配置文件 在终端中输入…

手撕LRU缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回 -…

python虚拟环境的概念,操作(pycharm为例)

1.在PyCharm中创建python项目时&#xff0c;需要配置python的运行环境&#xff0c;除了使用系统现有环境以外&#xff0c;还可以创建虚拟环境。 2.虚拟环境的创建是因为在实际开发中需要同期用到不同版本的python解释器&#xff0c;不同的第三方库以及同一个第三方库的不同版本…