山东大学操作系统实验六报告死锁问题
死锁进程实验报告

死锁进程实验报告一、实验目的:观察死锁发生的现象,了解死锁发生的原因。
掌握如何判断死锁发生的方法。
二、实验分析:死锁现象是操作系统各个进程竞争系统中有限的资源引起的。
如果随机给进程分配资源,就可能发生死锁,因此就应有办法检测死锁的发生。
本次实验中采用“银行家算法”判断死锁的发生。
三、实验设计:本实验设计一个3个并发进程共享3种系统资源且每种系统资源有10个的系统。
系统能显示各种进程的进展情况以及检察是否有错误和死锁现象产生。
四、算法说明:“银行家算法”。
按每个进程的申请数量给各个进程试探性分配资源,看能否找个一个序列使各个进程都能正常运行结束。
若能,则不会发生死锁;若不能,则会发生死锁。
五、程序使用说明:一、本程序用于检测错误和是否会发生死锁。
系统有3个进程竞争3种系统资源,每种资源有10个。
二、输入各个进程的最大需求资源数目数组max[3]和已经得到的资源数目组[3],系统计算出各个进程还应申请的资源数目数组need[3]。
三、若进程最大需求数大于系统资源数(10),则出错;若进程申请的资源数目大于其需要的最大资源数目,则出错。
/*死锁实验源程序*/include<math.h>include<stdio.h>typedef struct{int state;int max[3];int alloc[3];int need[3];}Pc;int whefinish(Pc *p){if((p[0].state&&p[1].state&&p[2].state)==1) return 1;else return 0;}inpalloc(Pc *P,int *q1,int *q2){int m,n;for(m=0;m<3;m++)for(n=0;n<3;n++){scanf("%d",&p[m].alloc[n])p[m].need[n]=p[m].max[n]-p[m].alloc[n];q1[n]=q1[n]-p[m].alloc[n];if(p[m].need[n]>p[m].max[n])q2[n]=0;}Prlcess(Pcb *p1,int *p2,int *q){if(p1->need[0]<p2[0]&&p1->need[1]<p2[1]&&p1->need[2]<p2[2]) {P->state=0;p2[0]+=P->alloc[0];p2[1]+=p->alloc[1];p2[2]+=p->alloc[2];*p=3;}}main(){int i,j,n,x=0;int state[3],avil[3]={10,10,10}Pc pcb[3];for(i=0;i<3;i++)for(j=0;j<3;j++){scanf("%d",Pcb[i].max[j];if(Pcb[i].max[j]>10)state[i]=0;}if((state[0]&&state[1]&&state[2])==0) printf("error!\n");else{inpalloc(&Pcb,&avil[3],&state[3]);if((state[0]&&state[1]&&state[2])==0) printf("Error!\n");else{for(i=0;i<3;i++)for(j=0;j<3;j++)Process(&Pcb[j],&avil,&j);if(whefinish(&Pcb)==1)printf("all Pcbs are finishde!\n");else printf("Deally-Embrace!\n");}}}六、实验心得:通过这次实验使我对死锁的概念,死锁产生的原因,死锁是否会产生的判断算法,银行家算法,都有了更为深入和直观的了解以及掌握。
死锁实验报告

操作系统实验报告——死锁的检测与解除计科101班张昊翔1007300204一.实验目的掌握操作系统的进程管理与资源分配原理,掌握对操作系统安全性检验和死锁的解除的原理和方法。
二.实验原理死锁(Deadlocking)是在多用户或多进程状况下,为使用同一资源而产生的无法解决的争用状态,通俗地讲,就是两个用户各占用一个资源,两人都想使用对方的资源,但同时又不愿放弃自己的资源,就一直等待对方放弃资源,如果不进行外部干涉,就将一直耗下去。
死锁会造成资源的大量浪费,甚至会使系统崩溃。
在SQL Server 中解决死锁的原则是“牺牲一个比两个都死强”,即挑出一个进程作为牺牲者,将其事务回滚,并向执行此进程的程序发送编号为1205 的错误信息。
而防止死锁的途径就是不能让满足死锁条件的情况发生,为此,用户需要遵循以下原则:尽量避免并发地执行涉及到修改数据的语句;要求每个事务一次就将所有要使用的数据全部加锁,否则就不予执行;预先规定一个封锁顺序所有的事务,都必须按这个顺序对数据执行封锁,例如,不同的过程在事务内部对对象的更新执行顺序应尽量保持一致;每个事务的执行时间不可太长,对程序段长的事务可考虑将其分割为几个事务三.设计思路1.输入系统进程数量n和资源类型数量m。
2.输入每类资源的数量。
3.输入每个进程每类资源的最大需求量和已获资源量。
4.检验系统的安全系。
5.若检测结果为系统不安全,可以对死锁进行解除,直到安全为止,再检测。
6.重复5操作,直到所有进程运行完毕。
四.主要功能模块int Max[100][100]={0}; //各进程所需各类资源的最大需求;int Available[100]={0}; //系统可用资源;char Name[100]={0}; //资源的名称;int Allocation[100][100]={0}; //系统已分配资源;int Need[100][100]={0}; //还需要资源int Request[100]={0}; //请求资源向量;int Temp[100]={0}; //存放安全序列;int Work[100]={0}; //存放系统可提供资源;bool Finish[100]={0};//存放已完成的序列五.程序流程图通六.源代码// Deadlock.cpp : 定义控制台应用程序的入口点。
操作系统中的死锁问题及解决方法讨论

操作系统中的死锁问题及解决方法讨论在计算机科学中,死锁是指两个或多个进程互相等待对方释放资源,从而导致它们都无法继续执行的情况。
死锁是多道程序系统中常见的问题,如果不及时解决,会导致系统资源占用不当,影响系统的稳定性和性能。
死锁通常发生在进程之间相互竞争有限的资源时,例如内存、文件、网络连接等。
当一个进程持有一些资源并等待另一个进程持有的资源时,就可能发生死锁。
为了避免死锁问题,操作系统设计者提出了多种解决方法:1. 预防死锁:通过合理地设计系统资源分配算法,尽量避免进程发生死锁。
例如,可以使用银行家算法来保证资源请求序列是安全的,从而避免死锁的发生。
2. 避免死锁:在资源分配之前,系统可以根据当前的资源状态来判断是否分配资源会导致死锁,如果是,则不分配资源。
常用的避免死锁算法有资源分配图算法和银行家算法。
3. 检测死锁:系统可以周期性地检测系统中是否存在死锁情况,一旦检测到死锁,就采取相应的措施进行恢复。
常用的检测死锁算法有图论算法、银行家算法等。
4. 解除死锁:一旦系统检测到死锁的存在,就需要解除死锁。
解除死锁的常用方法包括资源剥夺和进程终止。
资源剥夺是指系统剥夺一些进程的资源,以解除死锁;进程终止是指系统终止一些进程,以释放资源。
死锁问题是操作系统中一个重要且常见的问题,在设计和使用操作系统时,需要重视死锁问题并采取相应的预防和解决措施。
合理地设计系统资源分配策略、优化进程调度算法、定期检测死锁情况等都可以帮助系统避免死锁,提高系统的可靠性和稳定性。
操作系统的死锁问题及解决方法一直是计算机科学领域的研究热点,希望未来能够提出更加有效的死锁预防和解决方案,为操作系统的稳定性和性能提供更好的保障。
死锁实验报告

死锁实验报告
摘要:
本实验旨在通过模拟死锁现象,了解死锁的形成原因、必要条件以及常见的预防和解决死锁的方法。
通过使用Java编程语言,实现了一个简单的死锁实验场景,并对死锁的产生和解决过程进行了探究。
引言:
死锁是多线程编程中一个常见的问题,也是一种非常棘手的并发bug。
在多线程环境下,当两个或多个线程相互等待对方释放资源时,便可能会陷入死循环,无法继续执行下去。
本实验将通过一个典型的死锁场景,展示死锁的产生和解决过程,以便更好地理解和应对死锁问题。
一、实验背景
1.1 死锁的定义
死锁是指在多线程编程中,两个或多个线程相互等待对方释放资源,从而导致所有线程都无法继续执行的一种状态。
1.2 死锁产生的必要条件
死锁产生的必要条件包括:互斥条件、请求和保持条件、不可
剥夺条件和循环等待条件。
1.3 死锁的影响
死锁的产生会导致程序无法正常执行,造成资源浪费和系统崩
溃等问题,严重影响系统的稳定性和性能。
二、实验目的
本实验旨在通过实际代码实现死锁场景,探究死锁的产生原因,了解死锁的必要条件,并尝试不同的方法进行死锁的解决和预防。
三、实验环境
本实验使用Java编程语言,在Java开发环境下进行实验。
四、实验步骤
4.1 实验准备
在Java编程环境下,创建一个简单的多线程程序,模拟死锁场景。
在程序中创建两个线程,并为每个线程分别分配一个资源。
操作系统中的死锁分析和解决方法

操作系统中的死锁分析和解决方法在计算机操作系统中,死锁是指两个或多个进程互相请求对方的资源而导致的无限等待状态,从而导致系统资源无法被释放和并发进程无法运行,这是一个非常棘手的问题,需要在系统设计阶段和编程阶段考虑和解决。
本文将深入探讨操作系统中的死锁分析和解决方法。
一、死锁的原因和特征1.1 原因发生死锁主要是因为系统中的资源分配不当和进程调度算法不合理,以下几种情况容易导致死锁的发生:互斥:资源只能同时被一个进程使用,当一个进程持有一个资源并请求另一个已被其他进程持有的资源时,就会发生死锁。
占有和等待:一个进程持有一个资源并请求其他资源时,不释放已拥有的资源,就会阻塞其他进程的资源获取。
非抢占:只能在进程完成任务时才能释放资源,不能抢占已分配的资源,造成其他进程无法获得所需资源。
循环等待:多个进程形成了一个资源循环等待的环,每个进程都在等待其它进程占有的资源,造成死锁。
1.2 特征死锁有如下的特征:互相竞争的进程循环地发出请求并阻塞等待资源。
必须有一个或多个资源被进程独占。
资源持有者必须等待一个或多个资源,以便在未来请求成功,这就造成了死循环,因此它是死锁。
二、死锁的检测方法检测死锁可以使用各种算法。
2.1 系统状态图系统状态图是死锁检测算法的重要方法,其基本思想是利用一个图形来表示系统进程与资源之间的关系,当且仅当环路上所有进程都在等待其它进程所控制的资源时,才判断系统当前进入了死锁状态。
因此,如果状态图中没有环,那么系统就没有死锁;否则,就存在死锁。
2.2 资源分配图资源分配图同样是死锁检测算法的主要方法,其基本思想是用直接图或无向图来表示系统中所有资源和进程之间的关系,并且每个进程节点只能有一种颜色,可以表示两种不同的状态:执行和阻塞。
如果某一进程所有节点都已被染黑,但并未完全配额时,就可能存在死锁。
2.3 安全序列安全序列是指与系统状态图相对应的进程调度序列,它可以用来判断是否会发生死锁。
操作系统中的死锁问题

操作系统中的死锁问题在操作系统中,死锁是一种非常严重的问题,它会导致系统的资源无法被释放,进而影响系统的正常运行。
死锁是一种非常复杂的现象,通常发生在多个进程之间,这些进程之间相互等待对方所持有的资源,导致都无法继续执行。
本文将从死锁的定义、原因、解决方法等方面进行探讨。
一、死锁的定义二、死锁的原因死锁的产生通常是由于系统资源的竞争导致的。
在多任务操作系统中,进程之间会竞争系统资源,当一个进程持有了某个资源后,其他进程就无法再次获取这个资源,从而导致进程之间相互等待,最终引发死锁。
死锁产生的原因主要有以下几点:1. 互斥:资源是互斥的,即同一时间只能被一个进程占用。
当一个进程占用了某个资源后,其他进程就无法再次获取这个资源,只能等待。
2. 请求与保持条件:一个进程在申请新的资源的仍保持对原有资源的占有。
3. 不可抢占条件:系统中的资源是不可抢占的,即只能由持有资源的进程来释放资源。
4. 循环等待:系统中存在一个进程循环等待资源的情况,导致所有进程都无法继续执行。
这些原因导致了系统资源的不合理分配和处理,从而引发了死锁问题。
三、死锁的解决方法针对死锁问题,操作系统设计者提出了一些解决方法,主要包括预防死锁、避免死锁、检测死锁和解除死锁。
1. 预防死锁:预防死锁的关键在于打破死锁产生的四个条件之一。
可以采取资源的有序分配,即按照一定的顺序分配资源,避免进程竞争资源造成死锁;或者可以采取资源的抢占机制,当一个进程无法获取所需资源时,可以抢占其他进程的资源等。
2. 避免死锁:避免死锁的关键在于动态地进行资源分配和释放。
可以采用银行家算法来避免死锁,即在分配资源之前,先进行系统状态的检查,确保分配资源不会导致死锁的发生。
3. 检测死锁:检测死锁是指通过系统监控和分析确定系统中是否存在死锁,并在发现死锁后采取相应的措施。
可以采用资源分配图来检测死锁,当资源分配图中存在环路时,即表示系统中存在死锁。
4. 解除死锁:一旦检测到系统中存在死锁,就需要进行死锁解除。
操作系统原理 第六章 死锁

1、资源分配图 系统由若干类资源构成,一类资源称为一个 资源类;每个资源类中包含若干个同种资源, 称为资源实例。 资源类:用方框表示(资源的不同类型) 资源实例:用方框中的黑圆点表示(存在于每个 资源中) 进程 :用圆圈中加进程名表示 分配边:资源实例进程 的一条有向边 申请边:进程资源类 的一条有向边
第六章 死锁
若对资源不加限制的分配可能导致进程 间由于竞争资源而相互制约以至无法继 续运行的局面,这就是死锁。
一、死锁的基本概念 1、死锁产生的原因 系统中两个或两个以上的进程无限期的 等待永远不可能发生的事件,则称这些 进程处于死锁状态中。
进程执行的速度 例6-1 对临时资源使用不加限制 例6-2 例6-3 生活中的例子: 独木桥 其他:wait signal操作顺序不对
二、死锁预防 1、破坏互斥条件 允许多个进程同时访问资源 2、破坏不剥夺条件 在允许进程动态申请资源的前提下:一 个进程在申请新资源的要求不能立刻得 到满足时,便处于等待状态。而一个处 于等待状态的进程的全部资源可以被剥 夺。
3、破坏“请求和保持”条件 静态资源分配法 资源预分配:进程开始之前,一次性分配他 所需要的全部资源。 主要问题: • 进程因等待所需要的资源阻塞时间过长 • 部分资源可能在相当长的时间内变得不 可用; • 进程一次性知道所需全部资源不太可能。
三、死锁避免 系统对进程发出的每一个系统能够满足 的资源申请进行动态检查,并根据检查 结果决定是否分配资源,如果分配后系 统可能发生死锁,则不予分配,否则予 以分配,这是一种保证系统不进入死锁 状态的动态策略。
1、安全和不安全状态 安全状态:在某一时刻,系统能按照某 种次序,如<P1,P2……Pn>来为并发进 程分配所需要的资源,直到最大需求, 使每个进程都顺利完成,则程此时的系 统状态为安全状态。此序列为安全序列。 不安全状态:某一时刻,不存在这样的 一个安全序列,则称为不安全状态。
操作系统中的死锁问题

死锁,顾名思义是一把没有钥匙的锁,指计算机系统、进 程陷入一种死循环的状态,常常定义为在系统进程集合中的每 个进程都在请求并等待其他进程所占有的资源,导致所有进程 都处于等待状态不能运行,形成死循环。在该状态中,没有终 止条件能使陷入死循环的进程得以解脱,从而也不能解开环路 使其他进程得以释放。由此引发了所有进程都陷入想得到资源 却又都得不到资源的局面。如果长期无法改变这种等待状态, 那么这种现象被称为“饥饿”。
2.1 资源有限,引发资源竞争
系统资源有限,而进程运行又要求占用足够多的资源。当 进程所需资源被另一进程所占,另一进程所需资源被其他进程 所占,循环往复,这就导致了所有进程都处于一个不能继续执 行的状态,此时系统处于死锁状态。
2.2 并发进程的执行次序非法
借助例子阐明,山谷内有仅容一人通过的洞口,大家顺序 通过,则可保持通畅,当发生混乱,一群人涌向洞口,则此时 就会造成洞口堵塞,导致谁也不能通过,进程也是如此,当其 执行顺序不合理时,进程进入死锁区,在死锁点产生死锁。
- 23 -
中国新技术新产品 2019 NO.8(下)
信息技术
能强占,资源只能被占有它的进程自主释放。4)循环环路等 待。死锁发生时,系统中存在着一条由至少 2 个进程组成的环 路,在这条环路中的每一个进程都在等待后一个进程所占资源 的释放,因此导致环路堵塞,使进程不能再继续运行。
4 处理死锁的办法
参考文献 [1] 吴柄章 .PLC 与变频器在桥式起重机控制系统改造中的应 用 [J]. 质量探索,2016(6):68-67. [2] 瞿俊杰,刘韩臣,倪青亮 . 变频器在桥式起重机中的应用 [J]. 设备管理与维修,2017(11):98-99. [3] 张彦广 .ABB ACS800系列变频器在桥式起重机的应用及相 关问题研究 [J]. 科技创新与应用,2016(31):148.
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机科学与技术学院操作系统实验报告实验题目:死锁问题在两个城市南北方向之间存在一条铁路,多列火车可以分别从两个城市的车站排队等待进入车道向对方城市行驶,该铁路在同一时间,只能允许在同一方向上行车,如果同时有相向的火车行驶将会撞车。
请模拟实现两个方向行车,而不会出现撞车或长时间等待的情况。
您能构造一个管程来解决这个问题吗?实验目的:通过本实验观察死锁产生的现象,考虑解决死锁问题的方法。
从而进一步加深对于死锁问题的理解。
掌握解决死锁问题的几种算法的编程和调试技术。
练习怎样构造管程和条件变量,利用管程机制来避免死锁和饥俄问题的发生。
硬件环境:Inter(R)Core(TM)i5-3210M CPU @ 2.50GHz 内存:4GB 硬盘:500G 软件环境:XUbuntu-Linux 操作系统Gnome 桌面 2.18.3BASH_VERSION='3.2.33(1)-releasegcc version 4.1.2gedit 2.18.2OpenOffice 2.3实验步骤:1、问题分析:管程-Monitor管程是一种高级抽象数据类型,它支持在它的函数中隐含互斥操作。
结合条件变量和其他一些低级通信原语,管程可以解决许多仅用低级原语不能解决的同步问题。
利用管程可以提供一个不会发生死锁或饥饿现象的对象;哲学家就餐问题和 Java语言中的 synchronized 对象都是很好的管程的例子.管程封装了并发进程或线程要互斥执行的函数。
为了让这些并发进程或线程在管程内互斥的执行,进入管程的进/线程必须获取到管程锁或二值信号量条件变量 Condition Variables条件变量提供了一种对管程内并发协作进程的同步机制。
如果没有条件变量,管程就不会有很有用。
多数同步问题要求在管程中说明条件变量。
条件变量代表了管程中一些并发进程或线程可能要等待的条件。
一个条件变量管理着管程内的一个等待队列。
如果管程内某个进程或线程发现其执行条件为假,则该进程或线程就会被条件变量挂入管程内等待该条件的队列。
如果管程内另外的进程或线程满足了这个条件,则它会通过条件变量再次唤醒等待该条件的进程或线程,从而避免了死锁的产生。
所以,一个条件变量 C 应具有两种操作 C.wait()和 C.signal()。
当管程内同时出现唤醒者和被唤醒者时,由于要求管程内的进程或线程必须互斥执行,因此就出现了两种样式的条件变量:Mesa Style(signal-and-continue):唤醒者进程或线程继续执行,被唤醒者进程或线程等到唤醒者进程或线程阻塞或离开管程后再执行。
Hoare Style(signal-and-wait): 被唤醒者进程或线程立即执行,唤醒者进程或线程阻塞,直道被唤醒者阻塞或离开管程后再执行。
实验6 单行道(过桥)问题可以通过管程很好的解决。
可以把单行道/桥封装为一个管程类,桥上通过的车辆是进入管程的进/线程,可以通过创建多个车辆进/线程并随机产生它们的行进方向,并指定桥上可同时行驶的车辆的个数来模拟该问题的各种现场随机情况。
一个正确的实验结果应能实现在各种随机现场情况下车辆进程不会逆向上桥(死锁),也不会使车少方向上的车辆无机会上桥(饥饿).2、算法设计说明如下:以下是一个单行道管程类及其方法和属性的大致描述:定义一个单行道管程类:class OneWay {public:OneWay();~OneWay();void Arrive(int direc);// 车辆准备上单行道,direc 为行车方向void Cross(int direc);// 车辆正在单行道上void Quit(int direc);// 车辆通过了单行道private:int rate;//车速int *maxCars;//最大同向车数int *numCars;//当前正在通过的车辆数int *currentDirec;//当前通过的车辆的方向Condition *OneWayFull; //通过单行道的条件变量Lock *lock;//单行道管程锁};定义一个进入管程的信号量 Sema 类和锁 Lock 类(可参考实验六的示例程序).定义一个单行道管程的条件变量类:class Condition {public:Condition(Sema *sema1 , Sema *sema2);~Condition();void Wait(Lock *conditionLock,int direc); //过路条件不足时阻塞void Signal( int direc);//唤醒相反方向阻塞车辆private:Sema* queue1; // 一个方向阻塞队列Sema* queue2; // 另一方向阻塞队列Lock* lock;// 进入管程时获取的锁};Mesa 型条件变量的 Wait 和 Signal 方法:(也可设计成 Haoro 样式)Condition::Wait( Lock *conditionLock,int direct){保存当前条件锁;释放锁;进入所在方向等待队列睡眠;被唤醒后重新获取锁;}Condition::Signal( Lock *conditionLock){唤醒相反方向队列等待者}单行道管程的 Arrive 和 Quit 方法:OneWay::Arrive(int direc)获取管程锁;如果当前方向不是我的方向或者单行道上有车且车辆数大于等于上限数在条件变量上等待;单行道上车辆数加 1;当前方向为我的方向;释放管程锁;}OneWay::Quit(int direc){获取管程锁;单行道上车辆数减 1;车辆数为 0唤醒相反方向队列中的等待者释放管程锁}主程序main(){建立单行道管程;建立多个行车子进程(最好不少于 5 个),每个随机设定一个行车方每个子进程作:while(1){单行道管程->Arrive(direc);单行道管程->Cross(direc);单行道管程->Exit(direc);}}3、开发调试过程:在1、单行道最多允许一辆车行驶,不同方向同时到达五辆车。
$ ./dp 5 12、单行道最多允许两辆车同向行驶,不同方向同时到达七辆车。
./dp 7 2附件::#include "dp.h" Sema::Sema(int id) {sem_id = id;}Sema::~Sema(){ }int Sema::down(){struct sembuf buf;buf.sem_op = -1;buf.sem_num = 0;buf.sem_flg = SEM_UNDO;if((semop(sem_id,&buf,1)) <0) {perror("down error "); exit(EXIT_FAILURE); }return EXIT_SUCCESS; }int Sema::up(){Sem_uns arg;struct sembuf buf; buf.sem_op = 1;buf.sem_num = 0;buf.sem_flg = SEM_UNDO;if((semop(sem_id,&buf,1)) <0) { perror("up error ");exit(EXIT_FAILURE);}return EXIT_SUCCESS;}Lock::Lock(Sema * s){sema = s;Lock::~Lock(){ }//上锁void Lock::close_lock() {sema->down();}//开锁void Lock::open_lock() {sema->up();//用于哲学家就餐问题的条件变量Condition::Condition(Sema *s0, Sema *s1) { sema[0] = s0;sema[1] = s1;}void Condition::Wait(Lock *lock,int dir) {lock->open_lock();sema[dir]->down();lock->close_lock();}void Condition::Signal(int dir){sema[dir]->up();}int dp::get_ipc_id(char *proc_file,key_t key) {#define BUFSZ 256FILE *pf;int i,j;char line[BUFSZ],colum[BUFSZ];if((pf = fopen(proc_file,"r")) == NULL){ perror("Proc file not open");exit(EXIT_FAILURE);}fgets(line, BUFSZ,pf);while(!feof(pf)){i = j = 0;fgets(line, BUFSZ,pf);while(line[i] == ' ') i++;while(line[i] !=' ') colum[j++] = line[i++]; colum[j] = '\0';if(atoi(colum) != key) continue;j=0;while(line[i] == ' ') i++;while(line[i] !=' ') colum[j++] = line[i++]; colum[j] = '\0';i = atoi(colum);fclose(pf);return i;}fclose(pf);return -1;}int dp::set_sem(key_t sem_key,int sem_val,int sem_flg) {int sem_id;Sem_uns sem_arg;//测试由sem_key 标识的信号量是否已经建立if((sem_id=get_ipc_id("/proc/sysvipc/sem",sem_key)) < 0 ){//semget 新建一个信号灯,其标号返回到sem_id if((sem_id = semget(sem_key,1,sem_flg)) < 0){ perror("semaphore create error");exit(EXIT_FAILURE);}}//设置信号量的初值sem_arg.val = sem_val;if(semctl(sem_id,0,SETV AL,sem_arg) < 0){ perror("semaphore set error");exit(EXIT_FAILURE);}return sem_id;}char * dp::set_shm(key_t shm_key,int shm_num,int shm_flg) {int i,shm_id;char * shm_buf;//测试由shm_key 标识的共享内存区是否已经建立if((shm_id=get_ipc_id("/proc/sysvipc/shm",shm_key))<0){ //shmget 新建一个长度为shm_num 字节的共享内存if((shm_id= shmget(shm_key,shm_num,shm_flg)) <0){ perror("shareMemory set error");exit(EXIT_FAILURE);}//shmat 将由shm_id 标识的共享内存附加给指针shm_buf if((shm_buf=(char *)shmat(shm_id,0,0)) < (char *)0){perror("get shareMemory error");exit(EXIT_FAILURE);}for(i=0; i<shm_num; i++) shm_buf[i] = 0; //初始为0}//共享内存区已经建立,将由shm_id 标识的共享内存附加给指针shm_bufif((shm_buf = (char *)shmat(shm_id,0,0)) < (char *)0) {perror("get shareMemory error");exit(EXIT_FAILURE);}return shm_buf;}//哲学家就餐问题管程构造函数dp::dp(int r, int max){int ipc_flg = IPC_CREAT | 0644;int shm_key = 220;int shm_num = 5;int sem_key = 120;int sem_val = 0;int shm_flg = IPC_CREAT|0644; int sem_id;Sema *sema;Sema *sema1;Sema *sema2;rate = r;maxCars = max;// currentDirec = 1;numCars = 0;//共享内存,保存当前车辆数buff_ptr = (int*)set_shm(shm_key++, shm_num, shm_flg);put_ptr = (int *) set_shm(shm_key, 1, shm_flg);buff_ptr[*put_ptr] = 0; //车辆数buff_ptr[*put_ptr + 1] = 0; //记录是否为第一辆车buff_ptr[*put_ptr + 2] = 0; //当前方向超出最大车辆数buff_ptr[*put_ptr + 3] = 0; //反方向车辆数buff_ptr[*put_ptr + 4] = 0; //记录当前方向//5 个中同时可以有 2 个在就餐,建立一个初值为 2 的用于锁的信号灯if((sem_id = set_sem(sem_key++,1,ipc_flg)) < 0){perror("Semaphor create error");exit(EXIT_FAILURE);}sema = new Sema(sem_id);lock = new Lock(sema);//为每个哲学家建立初值为0 的用于条件变量的信号灯if((sem_id = set_sem(sem_key++,sem_val,ipc_flg)) < 0){perror("Semaphor create error");exit(EXIT_FAILURE);}sema1 = new Sema(sem_id);if((sem_id = set_sem(sem_key++,sem_val,ipc_flg)) < 0){ perror("Semaphor create error");exit(EXIT_FAILURE);}sema2 = new Sema(sem_id);con = new Condition(sema1, sema2);//共享内存互斥信号量sem_id = set_sem(sem_key++, 1, ipc_flg);mutex = new Sema(sem_id); }void dp::Arrive(int direc){int count;lock->close_lock();// numCars = getNum();mutex->down();count = buff_ptr[*put_ptr + 1];mutex->up();if(count == 0){currentDirec = direc;mutex->down();buff_ptr[*put_ptr + 4] = direc;buff_ptr[*put_ptr + 1] = ++count;mutex->up();}printf("%d号车从%d方向等待单行道……\n", getpid(), direc); mutex->down();currentDirec = buff_ptr[*put_ptr + 4];mutex->up();if(currentDirec != direc) {mutex->down();count = buff_ptr[*put_ptr + 3];buff_ptr[*put_ptr + 3] = ++count;mutex->up();con->Wait(lock, direc);}sleep(1);// currentDirec = direc;lock->open_lock();}void dp::Cross(int direc){int count, i;lock->close_lock();for(i = 0; i < 30; i++){numCars = getNum();if(numCars >= maxCars){mutex->down();count = buff_ptr[*put_ptr + 2];buff_ptr[*put_ptr + 2] = ++count;mutex->up();con->Wait(lock, direc);}}addNum();printf("%d号车从%d方向进入单行道-->\n", getpid(), direc); sleep(1);numCars = getNum();printf("%d号车从%d方向通过单行道,道上车数:%d\n", getpid(), direc, numCars);sleep(rate);lock->open_lock();}void dp::Leave(int direc){int count, num;lock->close_lock();printf("%d号车从%d方向离开单行道……\n", getpid(), direc);decNum();sleep(1);numCars = getNum();mutex->down();count = buff_ptr[*put_ptr + 3];num = buff_ptr[*put_ptr + 2];mutex->up();// printf("count:%d\n", count);// printf("num:%d\n", num);// printf("numCars:%d\n", numCars);if(numCars == 0 && count != 0){// printf("唤醒方向%d\n", 1 - direc);while(count--){con->Signal(1 - direc);}mutex->down();buff_ptr[*put_ptr + 4] = 1 - direc;buff_ptr[*put_ptr + 3] = buff_ptr[*put_ptr + 2];buff_ptr[*put_ptr + 2] = 0;buff_ptr[*put_ptr] = 0;mutex->up();}else if(numCars == 0 && num != 0){// printf("唤醒同方向%d\n", direc);while(num--){con->Signal(direc);}mutex->down();buff_ptr[*put_ptr + 2] = 0;buff_ptr[*put_ptr] = 0;mutex->up();}lock->open_lock();}dp::~dp(){ }int dp::getNum(){mutex->down();int num = buff_ptr[*put_ptr];mutex->up();return num;}void dp::addNum(){mutex->down();int num = buff_ptr[*put_ptr];buff_ptr[*put_ptr] = ++num;mutex->up();}void dp::decNum(){mutex->down();int num = buff_ptr[*put_ptr];buff_ptr[*put_ptr] = --num;mutex->up();}// 哲学家就餐问题并发执行的入口int main(int argc,char *argv[]){dp *tdp;//哲学家就餐管程对象的指针// int pid[5]; //5 个哲学家进程的进程号int cars;int dir;// int pid[5];int pid;int max = 2;int rate = 3;// rate = (argc > 1) ? atoi(argv[1]) : 3 ;cars = (argc > 1) ? atoi(argv[1]) : 5;max = (argc > 2) ? atoi(argv[2]) : 2;tdp = new dp(rate, max); //建立一个哲学家就餐的管程对象start:if((pid = fork()) == 0){srand(getpid());dir = rand() % 2;tdp->Arrive(dir);tdp->Cross(dir);tdp->Leave(dir); }else{if(--cars){goto start;}}return 0;}Dp.h:#include <iostream>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/msg.h> #include <sys/wait.h>using namespace std;typedef union semuns {int val;} Sem_uns;enum State {waiting, running};//哲学家管程中使用的信号量class Sema{public:Sema(int id);~Sema();int down(); //信号量加1int up(); //信号量减1 private:int sem_id; //信号量标识符};//哲学家管程中使用的锁class Lock{public:Lock(Sema *lock);~Lock();void close_lock();void open_lock();private:Sema *sema; //锁使用的信号量};//哲学家管程中使用的条件变量class Condition {public:Condition(Sema *sema1 , Sema *sema2);~Condition();void Wait(Lock *conditionLock,int direc); //过路条件不足时阻塞void Signal( int direc); //唤醒相反方向阻塞车辆private:Sema* sema[2]; // 一个方向阻塞队列// Sema* queue2; // 另一方向阻塞队列Lock* lock; // 进入管程时获取的锁};//哲学家管程的定义class dp{public:dp(int rate, int max);~dp();void Arrive(int direc); // 车辆准备上单行道,direc 为行车方向void Cross(int direc); // 车辆正在单行道上void Leave(int direc); // 车辆通过了单行道int getNum();void addNum();void decNum();//建立或获取ipc 信号量的一组函数的原型说明int get_ipc_id(char *proc_file,key_t key);int set_sem(key_t sem_key,int sem_val,int sem_flag);//创建共享内存,放哲学家状态char *set_shm(key_t shm_key,int shm_num,int shm_flag); private:int rate; //车速int maxCars; //最大同向车数int numCars; //当前正在通过的车辆数int currentDirec; //当前通过的车辆的方向Condition *con; //通过单行道的条件变量Lock *lock; //单行道管程锁int* buff_ptr;int* put_ptr;Sema *mutex; };Makefile:head = dp.hsrcs = objs = dp.oopts = -w -g -c all: dpdp: $(objs)g++ $(objs) -o dp dp.o: $(srcs) $(head) g++ $(opts) $(srcs) clean:rm dp *.o。