专业班级:计科1602S学号:2016190432105姓名:lsimplehappy实验三死锁的避免一、实验目的当系统的总资源数m小于或等于所有进程对资源的最大需求时,就可能产生死锁。死锁会引起计算机系统的瘫痪。银行家算法是在实现资源分配时避免死锁的一个著名算法,该算法是在能确保系统处于安全状态时才把资源分配给申请者。通过本实验使学生能进一步理解死锁的概念,并能选择一个算法来避免死锁。采用银行家算法来预防死锁是可靠的,但也是非常保守的,因为它限制了进程对资源的存取,从而降低了进程的并发运行程度。死锁检测并不限制进程对资源的申请,只要有,就分配,但这也可能造成死锁。但由于死锁并不是经常发生的,故大大提高了系统运行的效率。通过本实验,可使学生进一步加深理解和掌握死锁的检测算法。二、实验环境C/C++/C#Cfree/MicrosoftVisualStudio6.0/MicrosoftVisualStudio.NET2005三、实验的重点和难点1、避免死锁的实质在于如何防止系统进入不安全状态。2、在银行家算法中用到了可利用资源向量Available、最大需求矩阵Max、分配矩阵Allocation、需求矩阵Need等数据结构,而在安全性检查算2法中则还要用到工作向量Work和完成向量Finish等数据结构。3、安全性检查算法的目的是寻找一个安全序列。四、实验内容系统中有m个同类资源被n个进程共享,每个进程对资源的最大需求数分别为S1,S2,…,Sn,且Max(Si)=m,(i=1,2,…n)。进程可以动态地申请资源和释放资源。编写一个程序,实现银行家算法,当系统将资源分配给某一进程而不会死锁时,就分配之。否则,推迟分配,并显示适当的信息。数据结构和操作说明参照教材上有关银行家算法的资源分配表,设计适当的数据结构。进程要分配的资源数可由随机数决定或命令行输入,但要注意数据的有效范围。分别使用检测“进程—资源循环等待链”的方法来检测进程的死锁状态。对于相同的进程资源分配、占用次序,比较两个算法的结果。数据结构死锁检测算法的数据结构参考书教材资源占用矩阵、进程等待资源矩阵Q、资源总数向量和可用资源向量W。检测“进程—资源循环等待链”的算法可对所有的资源和进程进行编号,并设置一张资源分配表和一张进程等待表。五、实验要求:画出实现银行家算法的程序框图,说明数据结构。在每当进程要分配资源时以及释放资源后,打印输出资源分配或释放后的分配情况表,如可能产生死锁,显示适当信息;如不会产生死锁,更新系统的资源分配状态表。画出所实现算法的框图,说明所采用的数据结构。进程和所申请的资源可用命令行或随机数决定,进行一次分配就检测死锁,输出所涉及的表格数据。34六、实验代码及实验结果:#includestdio.h#includestdlib.htypedefstruct{intA;intB;intC;}RES;#definefalse0#definetrue1//系统中所有进程数量#definePNUMBER3//最大需求矩阵RESMax[PNUMBER];//已分配资源数矩阵RESAllocation[PNUMBER];//需求矩阵RESNeed[PNUMBER];//可用资源向量RESAvailable={0,0,0};//安全序列intsafe[PNUMBER];voidsetConfig(){inti=0,j=0;5printf(================开始手动配置资源==================\n);//可分配资源printf(输入可分配资源\n);scanf(%d%d%d,&Available.A,&Available.B,&Available.C);//最大需求矩阵MAXprintf(输入最大需求矩阵%dx%d\n,PNUMBER,PNUMBER);for(i=0;iPNUMBER;i++){scanf(%d%d%d,&Max[i].A,&Max[i].B,&Max[i].C);}//已分配矩阵Allocprintf(输入已分配矩阵%dx%d\n,PNUMBER,PNUMBER);for(i=0;iPNUMBER;i++){scanf(%d%d%d,&Allocation[i].A,&Allocation[i].B,&Allocation[i].C);}//需求矩阵printf(输入需求矩阵%dx%d\n,PNUMBER,PNUMBER);for(i=0;iPNUMBER;i++){scanf(%d%d%d,&Need[i].A,&Need[i].B,&Need[i].C);}printf(================结束配置资源==================\n);}voidloadConfig(){FILE*fp1;6if((fp1=fopen(config.txt,r))==NULL){printf(没有发现配置文件,请手动输入!!!\n);setConfig();}else{inti=0;printf(发现配置文件,开始导入..\n);//可分配资源fscanf(fp1,%d%d%d,&Available.A,&Available.B,&Available.C);//最大需求矩阵MAXfor(i=0;iPNUMBER;i++){fscanf(fp1,%d%d%d,&Max[i].A,&Max[i].B,&Max[i].C);}//已分配矩阵Allocfor(i=0;iPNUMBER;i++){fscanf(fp1,%d%d%d,&Allocation[i].A,&Allocation[i].B,&Allocation[i].C);}//需求矩阵for(i=0;iPNUMBER;i++){fscanf(fp1,%d%d%d,&Need[i].A,&Need[i].B,&Need[i].C);}7}}//试探分配voidProbeAlloc(intprocess,RES*res){Available.A-=res-A;Available.B-=res-B;Available.C-=res-C;Allocation[process].A+=res-A;Allocation[process].B+=res-B;Allocation[process].C+=res-C;Need[process].A-=res-A;Need[process].B-=res-B;Need[process].C-=res-C;}//若试探分配后进入不安全状态,将分配回滚voidRollBack(intprocess,RES*res){Available.A+=res-A;Available.B+=res-B;Available.C+=res-C;Allocation[process].A-=res-A;Allocation[process].B-=res-B;Allocation[process].C-=res-C;Need[process].A+=res-A;Need[process].B+=res-B;Need[process].C+=res-C;}8//安全性检查boolSafeCheck(){RESWork;Work.A=Available.A;Work.B=Available.B;Work.C=Available.C;boolFinish[PNUMBER]={false,false,false};inti;intj=0;for(i=0;iPNUMBER;i++){//是否已检查过if(Finish[i]==false){//是否有足够的资源分配给该进程if(Need[i].A=Work.A&&Need[i].B=Work.B&&Need[i].C=Work.C){//有则使其执行完成,并将已分配给该进程的资源全部回收Work.A+=Allocation[i].A;Work.B+=Allocation[i].B;Work.C+=Allocation[i].C;Finish[i]=true;safe[j++]=i;i=-1;//重新进行遍历}}}//如果所有进程的Finish向量都为true则处于安全状态,否则为不安全状态for(i=0;iPNUMBER;i++){9if(Finish[i]==false){returnfalse;}}returntrue;}//资源分配请求boolrequest(intprocess,RES*res){//request向量需小于Need矩阵中对应的向量if(res-A=Need[process].A&&res-B=Need[process].B&&res-C=Need[process].C){//request向量需小于Available向量if(res-A=Available.A&&res-B=Available.B&&res-C=Available.C){//试探分配ProbeAlloc(process,res);//如果安全检查成立,则请求成功,否则将分配回滚并返回失败if(SafeCheck()){returntrue;}else{printf(安全性检查失败。原因:系统将进入不安全状态,有可能引起死锁。\n);printf(正在回滚...\n);RollBack(process,res);}10}else{printf(安全性检查失败。原因:请求大于可利用资源。\n);}}else{printf(安全性检查失败。原因:请求大于需求。\n);}returnfalse;}//输出资源分配表voidPrintTable(){printf(===================================资源分配表==================================\n);printf(ProcessMaxAllocationNeedAvailable\n);printf(ABCABCABCABC\n);printf(P0%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d\n,Max[0].A,Max[0].B,Max[0].C,Allocation[0].A,Allocation[0].B,Allocation[0].C,Need[0].A,Need[0].B,Need[0].C,Available.A,Available.B,Available.C);printf(P1%2d%2d%2d%2d%2d%2d%2d%2d%2d\n,Max[1].A,Max[1].B,Max[1].C,Allocation[1].A,Allocation[1].B,Allocation[1].C,Need[1].A,Need[1].B,Need[1].C);printf(P2%2d%2d%2d%2d%2d%2d%2d%2d%2d\n,Max[2].A,Max[2].B,Max[2].C,Allocation[2].A,Allocation[2].B,Allocation[2].C,Need[2].A,Need[2].B,Need[2].C);11printf(===============================================================================\n);}//银行家算法分配voidbanker(){charch;//判断输入的是否是安全状态PrintTable();printf(先检查初始状态是否安全。\n);if(SafeCheck()){printf(系统处于安全状态。\n);printf(安全序列是{P%d,P%d,P%d}。\n,safe[0],safe[1],safe[2]);}else{printf(系统处于不安全状态。程序将退出...\n);printf(执行完毕。\n);get