C++银行家算法避免死锁
- 格式:pdf
- 大小:91.87 KB
- 文档页数:11
c语言银行家算法在C语言中实现银行家算法,首先需要了解该算法的基本概念和原理。
银行家算法是一种避免死锁的资源分配算法,它模拟了银行贷款的过程。
当一个进程请求资源时,系统先检查分配后是否安全,如果是,则分配资源。
否则,进程必须等待,直到足够的资源可用。
以下是一个简单的银行家算法的C语言实现:```c#include <stdio.h>#define MaxProcs 5#define MaxResources 3int Allocation[MaxProcs][MaxResources] = {0};int Max[MaxProcs][MaxResources] = {0};int Allocation[MaxProcs][MaxResources] = {0};int Available[MaxResources] = {0};int Need[MaxProcs][MaxResources] = {0};int Work[MaxResources] = {0};int safeSeq[MaxProcs] = {0};int count = 0;void calcNeed() {for (int p = 0; p < MaxProcs; p++) {for (int r = 0; r < MaxResources; r++) {Need[p][r] = Max[p][r] - Allocation[p][r];}}}void checkSafe() {int finish[MaxProcs] = {0};int k, j;for (k = 0; k < MaxProcs; k++) {safeSeq[k] = -1;}while (count < MaxProcs) {for (k = 0; k < MaxProcs; k++) {if (finish[k] == 0) {for (j = 0; j < MaxResources; j++) {if (Need[k][j] > Work[j]) {break;}}if (j == MaxResources) {for (j = 0; j < MaxResources; j++) {Work[j] += Allocation[k][j];safeSeq[count++] = k;finish[k] = 1;}}}}}if (count == MaxProcs) {printf("系统是安全的\n");} else {printf("系统是不安全的\n");}}```。
避免死锁的一个著名算法:银行家算法死锁的避免,不是严格地限制死锁的必要条件,而是在系统运行过程中小心地避免死锁的最终发生。
最著名的死锁避免算法是银行家算法。
银行家算法是一种最有代表性的避免死锁的算法。
又被称为“资源分配拒绝”法在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。
为实现银行家算法,系统必须设置若干数据结构。
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
银行家算法:设Request(i)是进程Pi的请求向量,如果Request(i)[j]=k,表示进程Pi需要K个R(j)类型的资源。
当Pi发现资源请求后系统将进行下列步骤(1)如果Request(i)[j] <= Need[i,j],边转向步骤2),否则认为出错,因为它所请求的资源数已超过它所宣布的最大值。
(2)如果Request(i)[j] <= Available[i,j],便转向步骤3),否则,表示尚无足够资源,Pi需等待。
(3)系统试探着把资源分配给进程Pi,并需要修改下面数据结构中的数值;Available[j] = Available[j] - Request(i)[j];Allocation[i,j] = Allocation[i,j] + Request(i)[j];Need[i,j] = Need[i,j] - Request(i)[j];(4)系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。
模拟通过银行家算法避免死锁一、银行家算法产生的背景及目的1:在多道程序系统中,虽然节奏、虽然借助于多个进程的并发执行来改善系统的利用率,提高系统的吞吐量,但可能发生一种危险—死锁。
,死锁就是多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵局状态时,如无外力作用,他们将无法再向前进行,如再把信号量作为同步工具时,多个Wait和Signal操作顺序不当,会产生进程死锁。
然而产生死锁的必要条件有互斥条件,请求和保持条件,不剥夺条件和环路等待条件。
在预防死锁的几种方法中,都施加了较强的限制条件,在避免死锁的方法中,所施加的条件较弱,有可能获得令人满意的系统性能。
在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统都处于安全状态,便可避免死锁。
2:实验目的:让学生独立的使用编程语言编写和调试一个系统分配资源的简单模拟程序,了解死锁产生的原因及条件。
采用银行家算法及时避免死锁的产生,进一步理解课堂上老师讲的相关知识点。
银行家算法是从当前状态出发,逐个按安全序列检查各客户中谁能完成其工作,然后假定其完成工作且归还全部贷款,再进而检查下一个能完成工作的客户。
如果所有客户都能完成工作,则找到一个安全序列,银行家才是安全的。
二:银行家算法中的数据结构1:可利用资源向量Available。
这是一个含有m个元素的数组,其中的每个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态的改变。
如果Available[j]=k,z 则表示系统中现有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个。
银行家算法银行家算法是一种最有代表性的避免死锁的算法。
要解释银行家算法,必须先解释操作系统安全状态和不安全状态。
安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。
安全状态一定是没有死锁发生。
不安全状态:不存在一个安全序列。
不安全状态不一定导致死锁。
那么什么是安全序列呢?安全序列:一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j <i )当前占有资源量之和。
银行家算法:我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。
当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量。
若超过则拒绝分配资源,若没有超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前的申请量分配资源,否则也要推迟分配。
算法:n:系统中进程的总数m:资源类总数Available: ARRAY[1..m]ofinteger;Max: ARRAY[1..n,1..m] of integer;Allocation:ARRAY[1..n,1..m]of integer;Need:ARRAY[1..n,1..m] of integer;Request: ARRAY[1..n,1..m] of integer;符号说明:Available 可用剩余资源Max 最大需求Allocation已分配资源Need 需求资源Request请求资源当进程pi提出资源申请时,系统执行下列步骤:(“=”为赋值符号,“==”为等号)step(1)若Request<=Need, goto step(2);否则错误返回step(2)若Request<=Available, goto step(3);否则进程等待step(3)假设系统分配了资源,则有:Available=Available-Request;Allocation=Allocation+Request;Need=Need-Request若系统新状态是安全的,则分配完成若系统新状态是不安全的,则恢复原状态,进程等待为进行安全性检查,定义数据结构:Work:ARRAY[1..m] of integer;Finish:ARRAY[1..n]ofBoolean;安全性检查的步骤:step (1):Work=Available;Finish=false;step (2)寻找满足条件的i:a.Finish==false;b.Need<=Work;如果不存在,goto step(4)step(3)Work=Work+Allocation;Finish=true;gotostep(2)step (4) 若对所有i,Finish=true,则系统处于安全状态,否则处于不安全状态/* 银行家算法,操作系统概念(OS concepts Six Edition)reeditbyJohnnyhagen,SCAU,run atvc6.0*/#include"malloc.h"#include "stdio.h"#include "stdlib.h"#definealloclensizeof(struct allocation)#define maxlen sizeof(structmax)#define avalensizeof(struct available)#defineneedlen sizeof(structneed)#define finilensizeof(structfinish)#definepathlen sizeof(structpath)struct allocation{int value;structallocation *next;};struct max{int value;struct max*next;};struct available/*可用资源数*/{int value;struct available *next;};struct need /*需求资源数*/{int value;struct need *next;};struct path{intvalue;struct path *next;};structfinish{int stat;struct finish*next;};intmain(){int row,colum,status=0,i,j,t,temp,processtest;struct allocation *allochead,*alloc1,*alloc2,*alloctemp;struct max*maxhead,*maxium1,*maxium2,*maxtemp;struct available *avahead,*available1,*available2,*workhead,*work1,*work2,*worktemp,*worktemp1;struct need*needhead,*need1,*need2,*needtemp;structfinish *finihead,*finish1,*finish2,*finishtemp;struct path *pathhead,*path1,*path2;printf("\n请输入系统资源的种类数:");scanf("%d",&colum);printf("请输入现时内存中的进程数:");scanf("%d",&row);printf("请输入已分配资源矩阵:\n");for(i=0;i<row;i++){for(j=0;j<colum;j++){printf("请输入已分配给进程p%d的%c种系统资源:",i,'A'+j);if(status==0){allochead=alloc1=alloc2=(struct allocation*)malloc(alloclen);alloc1->next=alloc2->next=NULL;scanf("%d",&allochead->value);status++;}else{alloc2=(struct allocation*)malloc(alloclen);scanf("%d,%d",&alloc2->value);if(status==1){allochead->next=alloc2;status++;}alloc1->next=alloc2;alloc1=alloc2;}}}alloc2->next=NULL;status=0;printf("请输入最大需求矩阵:\n");for(i=0;i<row;i++){for(j=0;j<colum;j++){printf("请输入进程p%d 种类%c 系统资源最大需求:",i,'A'+j);if(status==0){maxhead=maxium1=maxium2=(struct max*)malloc(maxlen); maxium1->next=maxium2->next=NULL;scanf("%d",&maxium1->value);status++;}else{maxium2=(struct max *)malloc(maxlen);scanf("%d,%d",&maxium2->value);if(status==1){maxhead->next=maxium2;status++;}maxium1->next=maxium2;maxium1=maxium2;}}maxium2->next=NULL;status=0;printf("请输入现时系统剩余的资源矩阵:\n");for(j=0;j<colum;j++){printf("种类%c的系统资源剩余:",'A'+j);if(status==0){avahead=available1=available2=(struct available*)malloc(avalen); workhead=work1=work2=(struct available*)malloc(avalen);available1->next=available2->next=NULL;work1->next=work2->next=NULL;scanf("%d",&available1->value);work1->value=available1->value;status++;}else{available2=(struct available*)malloc(avalen);work2=(struct available*)malloc(avalen);scanf("%d,%d",&available2->value);work2->value=available2->value;if(status==1){avahead->next=available2;workhead->next=work2;status++;}available1->next=available2;available1=available2;work1->next=work2;work1=work2;}}available2->next=NULL;work2->next=NULL;status=0;alloctemp=allochead;maxtemp=maxhead;for(i=0;i<row;i++)for(j=0;j<colum;j++)if(status==0){needhead=need1=need2=(structneed*)malloc(needlen); need1->next=need2->next=NULL;need1->value=maxtemp->value-alloctemp->value;status++;}else{need2=(struct need*)malloc(needlen);need2->value=(maxtemp->value)-(alloctemp->value);if(status==1){needhead->next=need2;status++;}need1->next=need2;need1=need2;}maxtemp=maxtemp->next;alloctemp=alloctemp->next;}need2->next=NULL;status=0;for(i=0;i<row;i++){if(status==0){finihead=finish1=finish2=(struct finish*)malloc(finilen);finish1->next=finish2->next=NULL;finish1->stat=0;status++;}else{finish2=(struct finish*)malloc(finilen);finish2->stat=0;if(status==1){finihead->next=finish2;status++;finish1->next=finish2;finish1=finish2;}}finish2->next=NULL; /*Initialization compleated*/status=0;processtest=0;for(temp=0;temp<row;temp++){alloctemp=allochead;needtemp=needhead;finishtemp=finihead;worktemp=workhead;for(i=0;i<row;i++){worktemp1=worktemp;if(finishtemp->stat==0){for(j=0;j<colum;j++,needtemp=needtemp->next,worktemp=worktemp->next)if(needtemp->value<=worktemp->value)processtest++;if(processtest==colum){for(j=0;j<colum;j++){worktemp1->value+=alloctemp->value;worktemp1=worktemp1->next;alloctemp=alloctemp->next;}if(status==0){pathhead=path1=path2=(struct path*)malloc(pathlen);path1->next=path2->next=NULL;path1->value=i;status++;}else{path2=(structpath*)malloc(pathlen);path2->value=i;if(status==1){pathhead->next=path2;status++;}path1->next=path2;path1=path2;}finishtemp->stat=1;}else{for(t=0;t<colum;t++)alloctemp=alloctemp->next;finishtemp->stat=0;}}elsefor(t=0;t<colum;t++){needtemp=needtemp->next;alloctemp=alloctemp->next;}processtest=0;worktemp=workhead;finishtemp=finishtemp->next;}}path2->next=NULL;finishtemp=finihead;for(temp=0;temp<row;temp++) {if(finishtemp->stat==0){printf("\n系统处于非安全状态!\n");exit(0);}finishtemp=finishtemp->next;}printf("\n系统处于安全状态.\n");printf("\n安全序列为:\n");do{printf("p%d",pathhead->value);}while(pathhead=pathhead->next);printf("\n");return0;}。
c语言银行家算法实验报告C语言银行家算法实验报告引言:计算机科学领域中,操作系统的资源管理是一个十分重要的课题。
在多任务处理系统中,多个进程同时竞争有限的资源,如何合理地分配和调度资源,以保证系统的稳定性和效率,是一个关键问题。
银行家算法(Banker's Algorithm)是一种经典的资源分配算法,它通过分析系统的资源状态和进程的资源需求,来判断是否能够安全地分配资源,从而避免产生死锁。
一、实验目的本次实验旨在通过C语言编程实现银行家算法,加深对资源管理和死锁问题的理解,并通过实际案例验证银行家算法的有效性。
二、实验环境本次实验使用C语言进行编程,并在Linux操作系统下进行测试。
三、实验过程1. 设计数据结构在开始编写代码之前,我们需要先设计适合的数据结构来表示系统资源和进程的状态。
在银行家算法中,我们需要记录系统中的可用资源数量、各个进程的最大需求资源数量、已分配资源数量和需要资源数量等信息。
通过定义合适的数据结构,我们可以方便地进行资源的分配和回收。
2. 实现银行家算法根据银行家算法的原理,我们可以将其分为两个步骤:安全性检查和资源分配。
在安全性检查中,我们需要判断当前系统状态下是否存在安全序列,即是否能够满足所有进程的资源需求,避免死锁的发生。
在资源分配中,我们需要根据当前系统状态和进程的资源需求,动态地分配和回收资源。
3. 编写测试用例为了验证银行家算法的正确性和有效性,我们需要编写一些测试用例。
测试用例应该包括各种不同的进程资源需求和系统资源状态,以覆盖不同情况下的资源分配和回收。
4. 运行测试用例在编写完测试用例后,我们可以运行程序,观察输出结果。
通过比较实际输出与预期结果,我们可以判断银行家算法的正确性和有效性。
四、实验结果与分析通过运行多个测试用例,我们可以得出以下结论:1. 银行家算法能够有效地避免死锁的发生。
在安全性检查过程中,如果存在安全序列,那么系统可以继续分配资源,否则需要阻塞等待。
采用银行家算法避免死锁一、实验目的:观察死锁发生的现象,了解死锁发生的原因。
掌握如何判断死锁发生的方法。
二、实验分析:死锁现象是操作系统各个进程竞争系统中有限的资源引起的。
如果随机给进程分配资源,就可能发生死锁,因此就应有办法检测死锁的发生。
本次实验中采用“银行家算法”判断死锁的发生。
三、实验设计:本实验设计一个3个并发进程共享3种系统资源且每种系统资源有10个的系统。
系统能显示各种进程的进展情况以及检察是否有错误和死锁现象产生。
四、算法说明:“银行家算法”。
按每个进程的申请数量给各个进程试探性分配资源,看能否找到一个序列使各个进程都能正常运行结束。
若能,则不会发生死锁;若不能,则会发生死锁。
五、程序使用说明:1、本程序用于检测错误和是否会发生死锁。
系统有3个进程竞争3种系统资源,每种资源有10个。
2、输入各个进程的最大需求资源数目数组max[3]和已经得到的资源数目数组alloc [3],系统计算出各个进程还应申请的资源数目数组need[3]。
3、若进程最大需求数大于系统资源数(10),则出错;若进程申请的资源数目大于其需要的最大资源数目,则出错。
银行家算法的具体实现程序:#include <stdio.h>#define R 10#define P 10int SafeCheck(int n,int m,int Max[P][R],int Allocation[P][R],int Available[R],int Need[P][R]){int p,i,j, safeque[P],Work[R],Finish[P]={0},t=0,flag;printf("当前的工作向量为:");for(j=0;j<m;j++){Work[j]=Available[j];printf("%d,",Work[j]);}//设置Work向量while(t<n){//开始寻找可分配的进程for(i=0;i<n;i++){if(Finish[i]==1) flag=0;//跳过已分配结束的进程else flag=1;if(flag){p=i;for(j=0;j<m;j++)if(Need[p][j]>Work[j]) { p=-1; break; }}if(p==i){ printf("找到一个可分配的进程P%d!\n",p); break;} }//顺序循环查找可分配资源的进程if(p!=-1){safeque[t++]=p;//入栈保护Finish[p]=1;//标志该进程结束printf("当前的工作向量为:");for(j=0;j<m;j++){Work[j]+=Allocation[p][j];printf("%d,",Work[j]);}p=-1;//清空当前进程号,以便下一次寻找出新的进程}//找到可分配资源的进程,并重设Work向量else { printf("找不到一个可分配的进程!终止检查!"); break; } }if(t==n){printf("系统存在一个安全序列:");for(t=0;t<n;t++)printf("P%d->",safeque[t]);printf("\n");return 1;}else {printf("系统不安全!会产生死锁!\n"); return 0;}}void main(){int Available[R],Max[P][R],Allocation[P][R],Need[P][R];int i,n,m,j,p,Request[R];int safe1,safe2;//设置第一次检查与第二次检查正确与否的观察变量printf("输入进程总数:");scanf("%d",&n);printf("输入资源类数:");scanf("%d",&m);printf("系统中R0--R%d类资源可利用数(空格隔开):",m-1);for(i=0;i<m;i++){scanf("%d",&Available[i]);}for(i=0;i<n;i++){printf("P%d进程的每类资源的分配情况如下:\n",i);printf("\tR0--R%d类资源最大数(空格隔开):",m-1);for(j=0;j<m;j++){scanf("%d",&Max[i][j]);}printf("\tR0--R%d类资源已分配(空格隔开):",m-1);for(j=0;j<m;j++){scanf("%d",&Allocation[i][j]);Need[i][j]=Max[i][j]-Allocation[i][j];}printf("\tR0--R%d类资源需求数(空格隔开):",m-1);for(j=0;j<m;j++){printf("%d ",Need[i][j]);}printf("\n");}//初始化进程的资源分配表printf("——————-第一次安全性检查——————\n");safe1=SafeCheck(n,m,Max,Allocation,Available,Need);if(safe1){printf("输入请求请求进程P的进程号:");scanf("%d",&p);printf("输入请求的R0--R%d各类资源数(空格隔开):",m-1);for(j=0;j<m;j++){scanf("%d",&Request[j]);if(Request[j]>Need[p][j]){printf("所请求的该资源数大于该进程所需求的最大值!终止请求!");safe1=0;break;}if(Request[j]>Available[j]){printf("所请求的该资源数大于系统中所拥有的最大值!终止请求!");safe1=0;break;}}}//第一次安全检查系统安全后判断请求向量的正确性if(safe1){printf("——————-第二次安全性检查——————\n");for(j=0;j<m;j++){Allocation[p][j]+=Request[j];Need[p][j]=Max[p][j]-Allocation[p][j];Available[j]-=Request[j];}//第二次安全检查前试探分配资源给请求资源safe2=SafeCheck(n,m,Max,Allocation,Available,Need);if(safe2==0)for(j=0;j<m;j++){Allocation[p][j]-=Request[j];Need[p][j]=Max[p][j]-Allocation[p][j];Available[j]+=Request[j];}//安全检查失败后重新收回分配给请求进程的资源}}书上的银行家算法例题实现如下:分析:该程序找到的安全序列:第一次检查{p1,p3,p0,p2,p4}第二次检查{p1,p3,p0,p2,p4}虽然与书上例题不一致,但经检验可以找出如上安全序列。
实验六银行家算法避免死锁一.实验目的1、加深对死锁概念的理解2、能够利用银行家算法有效地避免死锁的发生、或检测死锁的存在二.实验内容及步骤本实验在winTC环境下实现,winTC安装程序在ftp上,请自行安装。
1.利用银行家算法写一个程序,判定系统的安全性。
已知某系统有5个进程P0,P1,P2,P3,P4,三类资源A、B、C。
死锁检测程序工作时0)。
#define m 3#define n 5main(){int test(int av[],int ned[],all[]);int available[m]={0,0,0},need[n][m];int allocation[n][m]={{0,1,0},{2,0,0},{3,0,3},{2,1,1},{0,0,2}};//已占有资源int i,j,g=1;int finish[n]={0,0,0,0,0};//已完成的进程clrscr();//清屏printf(“please input the need resource data\n”);for(i=0;i<n;i++)for(j=0;j<m;j++)scanf(“%d”,&need[i][j]);//输入各个进程需要的资源j=0;do{for(i=0;i<n;i++)if(finish[i]==0 && test(need[i],available,allocation[i])) finish[i]=1;j++;}while(j<n);for(i=0;i<n;i++)g=g&&finish[i];//判断各个进程是否在安全性算法内全部通过if(g)printf(“safe state”);elseprintf(“not safe state”);}三.实验讨论谈谈你今天上实验课的收获,存在的问题或疑问。
如果有实验内容以外的发现也可谈谈。
操作系统原理试题题库含答案(3)1、下述解决死锁的方法中,属于死锁避免策略的是( )。
A、银行家算法B、资源有序分配法C、资源分配图化简法D、撤消进程法正确答案: A2、进程有三种基本状态,可能的状态转换是( )。
A、就绪态到运行态、等待态到就绪态、运行态到等待态B、就绪态到运行态、就绪态到等待态、等待态到运行态C、就绪态到运行态、等待态到就绪态、等待态到运行态D、运行态到就绪态、就绪态到等待态、等待态到运行态正确答案: A3、在存储管理中,采用地址变换机构的目的是()A、加快进程空间寻址B、提高CPU效率C、进程空间保护和内存共享D、便于有效分配内存正确答案: A4、关于碎片的说法以下哪个是正确的()。
A、静态页式存储管理中不存在碎片B、段页式存储管理中存在外碎片,但是不存在内碎片C、段式存储管理不存在内碎片D、页式存储管理既存在内碎片,也存在外碎片正确答案: C5、在面向用户的调度准则中,( )是选择分时系统中进程调度算法的重要准则。
A、响应时间快B、平均周转时间短C、截止时间的保证D、优先权高的作业能获得优先服务正确答案: A6、C语言编程中的printf函数属于()。
A、系统调用B、原语C、自定义函数D、库函数正确答案: A7、关于进程的运行、就绪和阻塞三个状态,下列观点正确的是()。
A、每个进程从创建到撤消都要经历这三个状态B、每个进程从创建到撤消,各个状态只能经历一次C、某些进程可以从阻塞状态转化为运行状态D、某些进程可以从运行状态转化为就绪状态正确答案: D8、在操作系统中引入线程的目的是____。
A、使多个程序能并发执行B、提高资源的利用率C、提高系统的吞叶量D、减少程序并发执行时的时空开销正确答案: D9、位示图方法可用于_____。
A、盘空间的管理B、盘的驱动调度C、文件目录的查找D、页式虚拟存贮管理中的页面调度正确答案: A10、一个进程是( )。
A、协处理器执行的程序B、一个独立的程序+数据集C、 PCB结构与程序和数据的集合D、一个独立的程序正确答案: C11、与计算机硬件关系最密切的软件是( )A、编译程序B、数据库管理程序C、游戏程序D、操作系统正确答案: D12、为了兼顾短作业和长时间等待的作业,应采用( )。
实验三预防进程死锁的银行家算法一、【实验目的】通过这次实验,加深对进程死锁的理解,进一步掌握进程资源的分配、死锁的检测和安全序列的生成方法。
二、【实验内容】问题描述:设计程序模拟预防进程死锁的银行家算法的工作过程。
假设系统中有n个进程P1, … ,P n,有m类可分配的资源R1, … ,R m,在T0时刻,进程P i分配到的j 类资源为Allocation ij个,它还需要j类资源Need ij个,系统目前剩余j类资源Work j个,现采用银行家算法进行进程资源分配预防死锁的发生。
三、【实验要求】程序要求:1)判断当前状态是否安全,如果安全给出安全序列;如果不安全给出理由。
2)对于下一个时刻T1,某个进程P k会提出请求Request(R1, … ,R m),判断分配给P k进程请求的资源之后系统是否安全。
3)输入:进程个数n,资源种类m,T0时刻各个进程的资源分配情况(可以运行输入,也可以在程序中设置);4)输出:如果安全,输出安全的进程序列,不安全则提示信息。
实现提示:用C++语言实现提示:1)程序中进程调度时间变量描述如下:int Available[MaxNumber];int Max[MaxNumber][MaxNumber];int Allocation[MaxNumber][MaxNumber];int Need[MaxNumber][MaxNumber];int Request[MaxNumber];int SafeOrder[MaxNumber];2)进程调度的实现过程如下:变量初始化;接收用户输入n,m,(输入或者默认的)Allocation ij,Need ij;按照银行家算法判断当前状态安全与否,安全给出安全序列,不安全给出提示;如果安全,提示用户输入下一时刻进程P k的资源请求Request(R1, … ,R m);如果不安全或者无新请求则退出。
四、【实验代码】#include<iostream>using namespace std;#define MaxNumber 100int Available[MaxNumber];//可利用资源int Max[MaxNumber][MaxNumber];//最大需求矩阵int Allocation[MaxNumber][MaxNumber];//分配矩阵int Need[MaxNumber][MaxNumber];//需求矩阵int Request[MaxNumber];//请求资源int SafeOrder[MaxNumber];//安全序列int ProcessNumber;int TypeNumber;bool Finish[MaxNumber];int Work[MaxNumber];int i,j,go=1;void init();bool bank();bool IsSafe();void init(){cout<<"请输入进程的个数:";cin>>ProcessNumber;cout<<"请输入资源种类的个数:";cin>>TypeNumber;for(i=0;i<ProcessNumber;i++){cout<<endl<<"P"<<i<<"已经分配:";for(j=0;j<TypeNumber;j++){cin>>Allocation[i][j];}cout<<"P"<<i<<"还需分配:";for(j=0;j<TypeNumber;j++){cin>>Need[i][j];Max[i][j]=Allocation[i][j]+Need[i][j];}}cout<<"请输入各类可利用资源个数:";for(j=0;j<TypeNumber;j++){cin>>Available[j];}}bool bank(){cout<<"请输入请求资源下标:";cin>>i;cout<<"P"<<i<<"请求各类资源数分别是:";for(j=0;j<TypeNumber;j++){cin>>Request[j];if(Request[j]>Need[i][j]){cout<<"请求资源超过其需要这类资源的最大值,请求失败";return false;}else if(Request[j]>Available[j]){cout<<"没有足够的资源,P"<<i<<"必须等待";return false;}}//银行家算法for(j=0;j<TypeNumber;j++){Available[j]=Available[j]-Request[j];Allocation[i][j]=Allocation[i][j]+Request[j];Need[i][j]=Need[i][j]-Request[j];}return true;}bool IsSafe(){for(i=0;i<ProcessNumber;i++){Finish[i]=false;}for(j=0;j<TypeNumber;j++){Work[j]=Available[j];}int flag=0,k=0;//flag用来控制while循环,使得每个进程都能重新检测到while(flag!=-1){for(i=0;i<ProcessNumber;i++){flag=-1;if(Finish[i]==false){for(j=0;j<TypeNumber;j++){if(Need[i][j]>Work[j])break;}if(j==TypeNumber){for(j=0;j<TypeNumber;j++){Work[j]=Work[j]+Allocation[i][j];Finish[i]=true;}SafeOrder[k]=i;//入安全序列k++;flag=1;//再次进行进程循环break;}}}}for(i=0;i<ProcessNumber;i++){if(Finish[i]==true&&i==ProcessNumber-1){cout<<"系统处于安全状态,存在一个安全序列是:{";for(i=0;i<ProcessNumber;i++)cout<<"P"<<SafeOrder[i]<<",";cout<<"}"<<endl;return true;}else if(Finish[i]==false){cout<<"系统进入不安全状态"<<endl;return false;}}}void main(){init();if(IsSafe()){while(go==1){cout<<endl<<"是否继续为进程分配资源(Y/N): ";char a;cin>>a;if(a=='Y'||a=='y'){if(bank()){if(IsSafe())cout<<"系统处于安全状态,请求成功"<<endl;else{cout<<"请求失败"<<endl;break;}}}else if(a=='N'||a=='n'){cout<<"没有进程请求资源"<<endl;break;}}}elsecout<<"该请求不安全,没有安全序列"<<endl; }五、【实验结果】。
算法的实现一、初始化由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。
二、银行家算法在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。
在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。
银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。
它是最具有代表性的避免死锁的算法。
设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。
(1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。
(2)如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i],则转(3);否则,出错。
(3)系统试探分配资源,修改相关数据:AVAILABLE[i]-=REQUEST[cusneed][i];ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];NEED[cusneed][i]-=REQUEST[cusneed][i];(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。
三、安全性检查算法运行安全性检查算法如下:1)Work = Available;Finish = false;2)寻找满足如下条件的i:Finish[i]==false并且Need[i]≤Work[i];如果不存在,则转步骤4);3)Work = Work + Allocation[i];Finish[i] = true;转步骤2);4)如果对于所有i,Finish[i] = true,则系统处于安全状态,否则处于不安全状态。
(1)设置两个工作向量Work=AVAILABLE;FINISH(2)从进程集合中找到一个满足下述条件的进程,FINISH==false;NEED<=Work;如找到,执行(3);否则,执行(4)(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。
避免死锁的银⾏家算法死锁的定义>如果⼀组进程中的每⼀个进程都在等待仅由该组进程中的其他进程才能引发的事件,那仫该组进程就是死锁的.产⽣死锁的必要条件>1).互斥条件:进程对所分配到的资源进⾏排它性使⽤,即在⼀段时间内,某资源只能被⼀个进程占⽤。
如果此时还有其他进程请求该资源,则请求资源只能等待,直⾄占有该资源的进程⽤毕释放.2).请求和保持条件:进程已经保持了⾄少⼀个资源,但⼜提出了新的资源请求,⽽该资源已经被其他进程占有,此时请求进程被保持,但对⾃⼰所获得的资源⼜保持不放.3).不可抢占条件:进程已获得的资源在未使⽤完之前不可被抢占,只能在使⽤完成后⾃⼰释放.4).环路等待:在发⽣死锁时,必然存在⼀个进程,资源的循环链.死锁产⽣的原因>1).竞争可重⽤不可抢占式的资源2).竞争可消耗资源3).进程推进顺序不当.可重⽤性资源:可供重复使⽤多次的资源.不可抢占性资源:⼀旦系统把某资源分配给该进程后,就不能将它强⾏收回,只能在进程使⽤完后⾃动释放.可消耗资源:⼜叫临时性资源,它是在进程运⾏期间,由进程动态的创建和消耗的.利⽤银⾏家算法解决死锁>1).银⾏家算法中的数据结构(1).可利⽤资源向量Available(2).最⼤需求矩阵Max(3).分配矩阵Allocation(4).需求矩阵Need2).银⾏家算法Request请求向量,(1).如果Request[i] <= Need[i][j]转下步,否则它所需要的资源数已超过它所需要的最⼤值(2).如果Request[i] <= Available[i][j]转下步,否则尚⽆⾜够资源,进程需等待(3).系统试分配给进程p,并修改Available,Allocation和NeedAvailable[j] -= Request[j]Allocation[i][j] += Request[j]Need[i][j] -= Request[j](4)系统执⾏安全性算法,检查此次资源分配后系统是否处于安全状态.若安全,才正式分配;否则恢复原来的分配状态,让该进程等待3).安全性算法(1).设置两个向量,⼯作向量Work,在执⾏安全性算法开始时 Work=Available;Finish:表⽰有⾜够的资源分配给进程,使之运⾏完成,Finish[i]=false;当有⾜够资源分配给进程时,再另Finish[i]=false(2).从进程集合中找到⼀个满⾜该条件的进程:Finish[i]=falseNeed[i][j] <= Work[j](3).当进程获得资源后,可顺利执⾏,并修改Work向量和Finsh向量Work[i] += Allocation[i][j]Finish[i]=true(4).如果所有进程的Finish[i]=true说明系统处于安全状态,否则系统处于不安全状态.在实现这份代码的时候陷⼊了⼀个误区那就是当你找到了⼀个安全序列之后,它查找过的Finish必定会被修改为true,⽽Finish这个数组⼜是在全局定义的,所以只要找到⼀次正确的安全序列这个Finish所找到的位就会被置为true会⼀直出现找到安全序列的,所以在找到安全序列之后⼀定要将Finish重新赋初值false,这个问题让我排错了半天,在定义变量的时候最好不要定义为全局的。