课程设计--理发师系统1_第1页
课程设计--理发师系统1_第2页
课程设计--理发师系统1_第3页
课程设计--理发师系统1_第4页
课程设计--理发师系统1_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、摘 要 课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。 通过对操作系统这门课的学习后,要求我们能够在深刻理解和应用有关经典进程的同步和互斥问题之余,能够模拟解决打瞌睡的理发师问题。要求以输出字符串的形式表示理发师和顾客的行为。理发师问题是一个利用信号量进行P、V操作的经典问题。设计程序实现此问题,要使得理发师的活动与顾客的活动得到各自真实的模拟。所执行的程序应体现:理发师在没有顾

2、客的时候去睡觉,有顾客则工作;顾客在理发师工作时坐下等待,无座时离开,直至等到理发师自己理发。关键字:理发师;顾客;PV操作 目 录摘 要11 设计要求11.1初始条件11.2技术要求12 需求分析22.1具体需求22.2系统实现步骤23 总体设计33.1总体设计思想33.2各功能之间的调用关系43.3创建数据结构64详细设计64.1控制营业开始的模块74.2建立一个理发类74.3理发功能模块85系统实现原理156程序运行界面186.1进入程序友好界面186.2理发店营业界面196.3理发店服务界面206.4 询问是否继续工作界面216.5 无顾客界面226.6理发店尚未营业的界面236.7退

3、出程序的界面237 设计总结24参考文献25致 谢26附录271 设计要求1.1初始条件(1)操作系统:Windos(2)程序设计语言:C+语言(3)设有三个理发师,3把椅子(另外还有三把理发椅),几把椅子可用连续 存储单元。1.2技术要求(1)为每个理发师顾客产生一个线程,设计正确的同步算法。(2)每个顾客进入理发室后,即时显示“work=1” 及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。(3)为每位顾客提供一个等待沙发(4)若等待人数达到上限则新来顾客离开理发店(5)若理发师理发人数达到3人,则可以询问理发师是否继续工作(6)若理发师工作状态为0,则理发店关门(7)若理

4、发师继续工作且无顾客则理发师进入睡眠状态(8)至多有6个顾客,每人理发至少3秒钟。(9)多个顾客须共享操作函数代码。 (10)本操作实现并发、并行、进程同步。2 需求分析2.1具体需求通过设计模拟解决打瞌睡的理发师问题,为理发店提供高效便捷的服务。理发店内有三名理发师,三把理发椅,和N把普通的椅子。要实现如果没有顾客来,那么理发师就坐在理发椅上打瞌睡;当顾客到来时,就唤醒理发师。如果顾客到来时理发师正在理发,顾客就坐下来等待。如果N把椅子都坐满了,顾客就离开该理发店到别处去理发。理发师刚开始理发时,先看看店里有没有顾客,如果没有,则在理发椅上打瞌睡;如果有顾客,则为等待时间最长的顾客理发,且等

5、待人数减1。顾客来到店里,先看看有无空位,如果没有空位,就不等了。离开理发店;如果有空位则等待,等待人数加1;如果理发师在打瞌睡,则将其唤醒。2.2系统实现步骤 这是一个很简单的程序,除了用到main()函数之外,还用到了一个lifa类函数来产生随机数、lifa()、lifashi();另外也用到了for循环和if嵌套语句。 设计的原理是:在开始程序是,先由程序员输入椅子数chairs,然后询问程序员是否开门营业:若程序员输入y,则开门营业;若输入n,则持续询问程序员是否营业。在刚开门营业之后,先随机产生顾客:若没顾客来,则理发师打瞌睡,再次进行产生顾客;若有顾客来,则直接为顾客理发。在为顾客

6、理发期间,程序自动产生顾客,最多产生3个顾客。顾客进来后,先看看理发师是否在理发,是则看看是否有空椅子,若有则坐下,无则离开。如果理发师正空闲,则直接为顾客理发。当理发完成之后,先判断已经为多少人理发了,如果未超过3人,则继续营业。若已超过,则询问程序员是否继续营业。若继续理发,则先判断是否有人等待,若有则先为等待最久的顾客理发,若没则理发师打瞌睡,程序继续回到随机产生顾客。3 总体设计3.1总体设计思想 题目中要求描述理发师和顾客的行为,本系统主要实现友好模块,以控制理发店是否开门营业。实现理发师理发模块,以控制理发师是否开始理发。实现顾客等待模块,以实现顾客是否选择等待。实现程序结束模块,

7、以实现理发师是否停止工作以便结束程序。因此需要两类线程lifashi()和lifa ()分别描述理发师和顾客的行为。其中,理发师有活动有理发和睡觉两个事件;等待和理发二个事件。店里有固定的椅子数,上面坐着等待的顾客,顾客在到来这个事件时,需判断有没有空闲的椅子,理发师决定要理发或睡觉时,也要判断椅子上有没有顾客。所以,顾客和理发师之间的关系表现为:(1)理发师和顾客之间同步关系:当理发师睡觉时顾客近来需要唤醒理发师为其理发,当有顾客时理发师为其理发,没有的时候理发师睡觉。(2)理发师和顾客之间互斥关系:由于每次理发师只能为一个人理发,且可供等侯的椅子有限只有n把,即理发师和椅子是临界资源,所以

8、顾客之间是互斥的关系。(3)故引入3个信号量和一个控制变量: <1>控制变量w用来记录等候理发的顾客数,初值为0; <2>控信号量c用来表示沙发数,初值为3; <3>信号量customers用来记录等候理发的顾客数,并用作阻塞理发师进 程,初值为0; <4>信号量finish用来记录已经完成理发的人数,并用作阻塞顾客进程,初值为0; (4)程序只有一个主体函数,用的是几个循环体来完成理发师和顾客的各项功能。 <1>用第一个循环体实现理发店是否开始营业的功能。 <2>用第二个循环体实现理发师是否开始理发的功能。 <3&

9、gt;在第二个循环体内设置控制程序结束的语句,可根据用户需 要而结束程序。 输出友好界面进入控制是否营业循环进入控制理发师理发循环 结束 开始 图3.1总体设计图3.2各功能之间的调用关系 (1) 友好模块是一个控制程序是否开始的循环体,用ii变量来控制循环体会询问用户是否开始程序。如果用户选择是,就执行后面的程序,如果选择否,就输出“对不起,理发店还没营业”,然后再次询问是否选择营业。(2) 理发师的控制模块是由另一个循环模块控制的,当没有顾客光临时,就输出“没有顾客光临,理发师可以休息”。当有顾客光临时,就开始继续运行下去,按照闲则服务,忙则等待,若等待人数超过三个就离开理发店的规则运行下

10、去。当服务人数超过三个,就询问是否还要继续服务。(3) 顾客等待模块,是一个判断等待条件是否成立的模块。若c-w>0,则顾客具备等待条件,否则等待条件不成立,顾客离开。 创建顾客进程结束 ii>3 创建理发师线程ii<=0初始化信号量 创建信号量 开始创建理发师线程失败创建理发师线程 c-w>0创建顾客进程失败 T F F T F T 图3.2主函数流程图3.3创建数据结构 定义一个理发类,便于主程序调用。加快进程调度,提高资源利用率,增大CPU吞吐量,减少内存空间。减少进程等待时间,使得程序清晰可读,处理机调用高速快捷。 class lifa;int c;/沙发数 i

11、nt customers=0;/顾客数 int count=0;/循环中用来计量的 int w=0;/等候理发的人数 int finish=0;/已经理完发的人数 int work1=0,work2=0,work3=0;/理发师是否在工作 char opendoor;/理发店是否开门接待顾客 int radom;/获取有无顾客数4详细设计定义一个lifa类,便于主函数调用。线程lifa()和lifashi()是两个公有函数,定义私有变量ii用来对进程进行控制,ii<=0 表示没有顾客,理发师处于休息状态。ii>0 表示理发店有顾客到来,对A、B、C三个理发师工作状态进行判断,若wo

12、rk=1,则顾客进入等待状态,则对c进行判断,若c-w>0,则顾客等待。反之理发店人已满,则顾客离开。若work=0,则顾客直接进行理发不用等待。变量customers自增1,等待变量w减1。若finish>2时,理发师理发人数已达到上限,询问理发师是否继续工作。jixu=“y” 则继续工作,jixu=“n” 则理发师休息。则程序结束,exit()=0。 主函数开始调用,进入友好界面若opendoor=“y”,则开门营业。若opendoor=“n”,则表示理发店尚未开门。4.1控制营业开始的模块这个功能的实现是用了一个循环,当询问是否开始营业是,用户有两个选择,一个是,一个否,当选

13、择是时,输出“理发店开门营业!”程序跳出该循环 进入下一个功能;当选择否时,输出“对不起,理发店还没有开门”然后继续询问是否营业。cout<<"是否营业?y/n"<<endl; cin>>opendoor; while(opendoor!='y') cout<<"对不起,理发店还没有开门!"<<endl; cout<<"是否营业?y/n"<<endl; cin>>opendoor; cout<<endl; cou

14、t<<"理发店开门营业!"<<endl;cout<<endl;4.2建立一个理发类 建立理发类的作用就是要在主函数中显得更简洁明了,不至于觉得繁琐。使用更方便,也方便改动程序。class lifa public: lifa(int i)ii=i; void lifashi(); private: int ii;4.3理发功能模块课程设计的主要目的是了解并且掌握进程之间的同步互斥,和进程之间的通信问题。结合课本上的生产者与消费者问题可以从这方面来实现一个多进程的小系统,并且解决多个进程之间的通信,并发等问题,以此来达到课程设计的目的。理发师

15、问题是将顾客看做生产者,将理发师作为消费者。设置一定数量的椅子的数目来作为缓存区的大小。顾客来到的时候坐在椅子上,将自己作为“产品”,理发师理发的时候从椅子上叫走顾客,相当于消费“产品”,从而达到了课程设计要求的前一个要求。 顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。并且,第1个到来的顾客应负责唤醒理发师;如果不是第1个到达的顾客,则在有空椅子的情况下坐下等待,否则离开理发店(该消息可由计数器count获得)。这是理发类中定义的一个控制理发师理发的函数。这里用了两个循环嵌套,中间小的一层是控制顾客来的数目,当有顾客来访,就

16、开始往下执行,判断理发师是否有空,如果有空,就进行理发,若没有空,就判断是否有空闲沙发可以让顾客等待,若果有空闲沙发,则顾客等待,若没有空闲沙发,顾客就离开理发店。理发完成就显示理发完成,完成数就加一,如果理发完成数大于三个人,就输出理发完成的状态和等待的顾客数。询问是否继续理发,如果否,则退出程序,如果是,则先为等待的顾客理发,完成后输出已完成。由于整个模块是由一个大的模块控制循环,所以你选择继续,则会又继续重复上面的功能,知道你选择退出程序。主要有以下一些函数来实现整个问题的实现过程: (1)用随机函数lifa()来产生进入理发店的顾客。 (2)定义理发师的理发函数lifashi()用来实

17、现理发操作。 (3)定义一个lifa类用来实现顾客被理发的操作。 (4)用顾客线程customer实现对顾客行为的控制。 (5)用状态量work实现对理发师行为的控制。 (6)定义主函数main实现对两个线程的控制和执行操作。Work=1 结束等待理发师线程结束创建顾客线程失败创建顾客线程 ii<9等待顾客线程结束理发师线程失败Work=0创建理发师线程信号量初始化失败 开始创建并初始化信号量Work!=0 F T T F F T F T 图4.3理发师功能流程图void lifa:lifashi() int c=3;/沙发数 int customers=0;/顾客数 int count

18、=0;/循环中用来计量的 int w=0;/等候理发的人数 int finish=0;/已经理完发的人数 int work1=0,work2=0,work3=0;/理发师是否在工作 char jixu,p;while(ii<=0) cout<<"没有顾客来理发,理发师坐在沙发上休息"<<endl<<endl; cout<<"请输入来的顾客数,输入0表示没有顾客来:"<<endl; cin>>ii; while(ii>0) for(count=0;count<=2;c

19、ount+) customers+; cout<<"第"<<customers<<"个顾客到来了。"<<endl; if(work1=1)/判断是否正为顾客理发,是则新来顾客等待,否则不用等待 if(w<c)/判断是否有空沙发 cout<<"有"<<c-w<<"张空沙发,顾客坐下等待。"<<endl; w+; else cout<<"没有空沙发,顾客离开。"<<endl;

20、 else cout<<"A理发师为第"<<customers<<"个顾客理发。"<<endl; work1=1; customers+; cout<<"第"<<customers<<"个顾客到来了。"<<endl; if(work2=1)/判断是否正为顾客理发,是则新来顾客等待,否则不用等待 if(w<c) /判断是否有空沙发 cout<<"有"<<c-w<<

21、;"张空沙发,顾客坐下等待。"<<endl; w+; else cout<<"没有空沙发,顾客离开。"<<endl; else cout<<"B理发师为第"<<customers<<"个顾客理发"<<endl; work2=1; customers+; cout<<"第"<<customers<<"个顾客到来了。"<<endl; if(work3

22、=1)/判断是否正为顾客理发,是则新来顾客等待,否则不用等待 if(w<c)/判断是否有空沙发 cout<<"有"<<c-w<<"把空沙发,顾客坐下等待。"<<endl; w+; else cout<<"没有空沙发,顾客离开。"<<endl; else cout<<"C理发师为第"<<customers<<"个顾客理发。"<<endl; work3=1; if(work1

23、=1) cout<<"A理发完成。"<<endl; work1=0;/理发完成,理发师空闲 finish+;/理发完人数加1 if(work2=1) cout<<"B理发完成。"<<endl; work2=0;/理发完成,理发师空闲 finish+;/理发完人数加1 if(work3=1) cout<<"C理发完成。"<<endl; work3=0;/理发完成,理发师空闲 finish+;/理发完人数加 if(finish>2) /完成为3个人理发的任务,询

24、问理发师是否继续工作 cout<<"已经为"<<finish<<"位顾客理发了,还有"<<w<<"个顾客在等待,是否继续工作?y/n"<<endl; cin>>jixu; if(jixu='n') cout<<"谢谢光临!"<<endl; exit(0); if(w>0) /看看是否有人在等待理发 cout<<"有"<<w<<&qu

25、ot;位顾客等待,A理发师继续为等待的第一位顾客理发"<<endl; w-; work1=1; /有则进入工作状态 if(w>0) /看看是否有人在等待理发 cout<<"有"<<w<<"位顾客等待,B理发师继续为等待的第二位顾客理发"<<endl; w-; work2=1;/有则进入工作状态 if(w>0) /看看是否有人在等待理发 cout<<"有"<<w<<"位顾客等待,C理发师继续为等待的第三位顾客理

26、发"<<endl; w-; work3=1;/有则进入工作状态 if(work1=1) cout<<"A将等待的顾客理发完成。"<<endl; work1=0;/理发完成,理发师空闲 finish+;/理发完人数加1 if(work2=1) cout<<"B将等待的顾客理发完成。"<<endl; work2=0;/理发完成,理发师空闲 finish+;/理发完人数加1 if(work3=1) cout<<"C将等待的顾客理发完成。"<<end

27、l; work3=0;/理发完成,理发师空闲 finish+;/理发完人数加1 cout<<"已经为"<<finish<<"位顾客理发了,还有0个顾客在等待,是否继续工作?y/n"<<endl; cin>>p; if(p='y') jixu=p; if(p='n') jixu=p; cout<<"谢谢光临!"<<endl; exit(0); 5系统实现原理目的:深入掌握进程调度的概念原理和实现方法。调试要求:编写一个进程

28、调度程序,允许多个进程并行执行。 进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)、先来先服务算法、按时间片轮转调度算法,最终总结该算法的优缺点。 每个进程有一个进程控制块(PCB)表示,进程控制块可以包含如下信息: 进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等。 进程的优先数及需要的运行时间可以事先人为指定(也可以由随机数产生)。进程的到达时间为输入进程的时间。进程的运行时间以时间片为单位进行计算。每个进程的状态可以是就绪W(wait)、运行R(run)或完成F(finish)三种状态之一。 如果运行下个时间片后,进程的已占用CPU时间已达

29、到所需要的运行时间,则撤消该进程,如果运行一个时间片后进行已占用CPU时间还未达到所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。重复以上过程,直到所有进程都完成为止。因为理发店的营业是持续的,在一个阶段完成后,怎么选择继续执行呢,这里我用了一个选择语句,然后利用循环不断地来完成这个过程。在顾客接受服务的过程中,有很多判断条件,以保证顾客的分类,到底是接受服务,还是等待,又或者是离开。这个功能是利用很多if语句来完成的。这里用的类的调用,使得主

30、函数变得简单,而在改动程序时也方便许多。特点:既照顾了短进程,又考虑了进程到达的先后次序,也不会使长进程长期得不到服务,因此是一个比较全面考虑的算法,但每次进行调度时,都需要对各个进程计算响应比。所以系统开销很大,比较复杂。 原理:每次调度是从就绪队列中,选择一个最先进入就绪队列的进程,把处理器分配给该进程,使之得到执行。该进程一旦占有了处理器,它就一直运行下去,直到该进程完成或因发生事件而阻塞,才退出处理器。特点:利于长进程,而不利于短进程。原理:它是从就绪队列中选择一个估计运行时间最短的进程,将处理器分配给该进程,使之占有处理器并执行,直到该进程完成或因发生事件而阻塞,然后退出处理器,再重

31、新调度。原理:它是从就绪队列中选择一个响应比最高的进程,让其获得处理器执行,直到该进程完成或因等待事件而退出处理器为止。 P原语操作如下: <1>sem减1。 <2>若sem减1后仍大于零,则P原语返回,该进程继续执行。sem>=0调用进程入等待队列转进程调度 返回Sem=sem-1 入口 <3>若sem减1后小于零,则该进程被阻塞后进入与该信号相对应的队列 中,然后转进程调度。 T F 图5.4 P原语操作功能图 V原语操作如下: <1>sem加1。 <2>若sem加1后仍大于零,则V原语停止执行,该进程返回调用处,继续执行。

32、 <3>若sem加1后小于或等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转进程调度。 返回或转进程调度Sem=sem+1Sem<=0 返回 入口Sem=sem+1Sem<=0 返回 入口 F T唤醒等待队列中一个进程 图5.5 V原语操作功能图6程序运行界面 6.1进入程序友好界面 进入程序友好界面,程序初始化c=3,则输出“理发店内总共有3张沙发” 给变量opendoor负值,以选择理发店是否开门。 图6.1 友好界面6.2理发店营业界面 若opendoor=“y”,则输出“理发店开门营业” ii的取值范围在19之间,输入0表示没有顾客上

33、门,输入随机数表示顾客数。 图6.2 营业界面6.3理发店服务界面 若opendoor=“y”,给变量ii赋值为2,则A、B、C三位理发师开始理发且对c-w进行判断,是否有空的沙发。有空沙发则顾客等待,没有空沙发则顾客离开。 图6.3 有顾客来的服务界面6.4 询问是否继续工作界面 当finish>2时,已经为3位顾客理完发。若opendoor=“y”,则表示理发师继续工作且三位等待的顾客都已经理完发,此时w=0。判断opendoor的状态。 图6.4 询问是否继续工作的界面6.5 无顾客界面 若变量 opendoor=“y”且ii=0,则输出“没有顾客来理发,理发师坐在沙发上休息” 表示理发店开门营业,但无顾客上门。 图6.5 没有顾客来的界面6.6理发店尚未营业的界面 若opendoor=“n”,则输出“理发店还没有开门” 图6.6 理发店尚未营业的界面6.7退出程序的界面若finish>2且jixu=“n” 表示已经达到顾客数上限,理发师不在理发。则输出“谢谢光临”,退出程序。 图6.7 退出程序的界面7 设计总结为期两个星期操作系统课程设计马上就要结束了,现在我来总结一下这两个星期所学的内容和感想。课程设计对学生而言是其对所学课程内容掌握情况的一次自我验证,从而有着极其重要

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论