课程设计理发师系统1.docx

上传人:b****7 文档编号:23936452 上传时间:2023-05-22 格式:DOCX 页数:30 大小:288.68KB
下载 相关 举报
课程设计理发师系统1.docx_第1页
第1页 / 共30页
课程设计理发师系统1.docx_第2页
第2页 / 共30页
课程设计理发师系统1.docx_第3页
第3页 / 共30页
课程设计理发师系统1.docx_第4页
第4页 / 共30页
课程设计理发师系统1.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

课程设计理发师系统1.docx

《课程设计理发师系统1.docx》由会员分享,可在线阅读,更多相关《课程设计理发师系统1.docx(30页珍藏版)》请在冰豆网上搜索。

课程设计理发师系统1.docx

课程设计理发师系统1

摘要

课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。

因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。

通过对《操作系统》这门课的学习后,要求我们能够在深刻理解和应用有关经典进程的同步和互斥问题之余,能够模拟解决打瞌睡的理发师问题。

要求以输出字符串的形式表示理发师和顾客的行为。

理发师问题是一个利用信号量进行P、V操作的经典问题。

设计程序实现此问题,要使得理发师的活动与顾客的活动得到各自真实的模拟。

所执行的程序应体现:

理发师在没有顾客的时候去睡觉,有顾客则工作;顾客在理发师工作时坐下等待,无座时离开,直至等到理发师自己理发。

关键字:

理发师;顾客;PV操作

目录

摘要1

1设计要求1

1.1初始条件1

1.2技术要求1

2需求分析2

2.1具体需求2

2.2系统实现步骤2

3总体设计3

3.1总体设计思想3

3.2各功能之间的调用关系4

3.3创建数据结构6

4详细设计6

4.1控制营业开始的模块7

4.2建立一个理发类7

4.3理发功能模块8

5系统实现原理15

6程序运行界面18

6.1进入程序友好界面18

6.2理发店营业界面19

6.3理发店服务界面20

6.4询问是否继续工作界面21

6.5无顾客界面22

6.6理发店尚未营业的界面23

6.7退出程序的界面23

7设计总结24

参考文献25

致谢26

附录27

1设计要求

1.1初始条件

(1)操作系统:

Windos

(2)程序设计语言:

C++语言

(3)设有三个理发师,3把椅子(另外还有三把理发椅),几把椅子可用连续存储单元。

1.2技术要求

(1)为每个理发师/顾客产生一个线程,设计正确的同步算法。

(2)每个顾客进入理发室后,即时显示“work=1”及其线程自定义标识,还同时显示理发室共有几名顾客及其所坐的位置。

(3)为每位顾客提供一个等待沙发

(4)若等待人数达到上限则新来顾客离开理发店

(5)若理发师理发人数达到3人,则可以询问理发师是否继续工作

(6)若理发师工作状态为0,则理发店关门

(7)若理发师继续工作且无顾客则理发师进入睡眠状态

(8)至多有6个顾客,每人理发至少3秒钟。

(9)多个顾客须共享操作函数代码。

(10)本操作实现并发、并行、进程同步。

2需求分析

2.1具体需求

通过设计模拟解决打瞌睡的理发师问题,为理发店提供高效便捷的服务。

理发店内有三名理发师,三把理发椅,和N把普通的椅子。

要实现如果没有顾客来,那么理发师就坐在理发椅上打瞌睡;当顾客到来时,就唤醒理发师。

如果顾客到来时理发师正在理发,顾客就坐下来等待。

如果N把椅子都坐满了,顾客就离开该理发店到别处去理发。

理发师刚开始理发时,先看看店里有没有顾客,如果没有,则在理发椅上打瞌睡;如果有顾客,则为等待时间最长的顾客理发,且等待人数减1。

顾客来到店里,先看看有无空位,如果没有空位,就不等了。

离开理发店;如果有空位则等待,等待人数加1;如果理发师在打瞌睡,则将其唤醒。

2.2系统实现步骤

这是一个很简单的程序,除了用到main()函数之外,还用到了一个lifa类函数来产生随机数、lifa()、lifashi();另外也用到了for循环和if嵌套语句。

设计的原理是:

在开始程序是,先由程序员输入椅子数chairs,然后询问程序员是否开门营业:

若程序员输入‘y’,则开门营业;若输入‘n’,则持续询问程序员是否营业。

在刚开门营业之后,先随机产生顾客:

若没顾客来,则理发师打瞌睡,再次进行产生顾客;若有顾客来,则直接为顾客理发。

在为顾客理发期间,程序自动产生顾客,最多产生3个顾客。

顾客进来后,先看看理发师是否在理发,是则看看是否有空椅子,若有则坐下,无则离开。

如果理发师正空闲,则直接为顾客理发。

当理发完成之后,先判断已经为多少人理发了,如果未超过3人,则继续营业。

若已超过,则询问程序员是否继续营业。

若继续理发,则先判断是否有人等待,若有则先为等待最久的顾客理发,若没则理发师打瞌睡,程序继续回到随机产生顾客。

3总体设计

3.1总体设计思想

题目中要求描述理发师和顾客的行为,本系统主要实现友好模块,以控制理发店是否开门营业。

实现理发师理发模块,以控制理发师是否开始理发。

实现顾客等待模块,以实现顾客是否选择等待。

实现程序结束模块,以实现理发师是否停止工作以便结束程序。

因此需要两类线程lifashi()和lifa()分别描述理发师和顾客的行为。

其中,理发师有活动有理发和睡觉两个事件;等待和理发二个事件。

店里有固定的椅子数,上面坐着等待的顾客,顾客在到来这个事件时,需判断有没有空闲的椅子,理发师决定要理发或睡觉时,也要判断椅子上有没有顾客。

所以,顾客和理发师之间的关系表现为:

(1)理发师和顾客之间同步关系:

当理发师睡觉时顾客近来需要唤醒理发师为其理发,当有顾客时理发师为其理发,没有的时候理发师睡觉。

(2)理发师和顾客之间互斥关系:

由于每次理发师只能为一个人理发,且可供等侯的椅子有限只有n把,即理发师和椅子是临界资源,所以顾客之间是互斥的关系。

(3)故引入3个信号量和一个控制变量:

<1>控制变量w用来记录等候理发的顾客数,初值为0;

<2>控信号量c用来表示沙发数,初值为3;

<3>信号量customers用来记录等候理发的顾客数,并用作阻塞理发师进程,初值为0;

<4>信号量finish用来记录已经完成理发的人数,并用作阻塞顾客进程,初值为0;

(4)程序只有一个主体函数,用的是几个循环体来完成理发师和顾客的各项功能。

<1>用第一个循环体实现理发店是否开始营业的功能。

<2>用第二个循环体实现理发师是否开始理发的功能。

<3>在第二个循环体内设置控制程序结束的语句,可根据用户需要而结束程序。

 

图3.1总体设计图

3.2各功能之间的调用关系

(1)友好模块是一个控制程序是否开始的循环体,用ii变量来控制循环体会询问用户是否开始程序。

如果用户选择是,就执行后面的程序,如果选择否,就输出“对不起,理发店还没营业”,然后再次询问是否选择营业。

(2)理发师的控制模块是由另一个循环模块控制的,当没有顾客光临时,就输出“没有顾客光临,理发师可以休息”。

当有顾客光临时,就开始继续运行下去,按照闲则服务,忙则等待,若等待人数超过三个就离开理发店的规则运行下去。

当服务人数超过三个,就询问是否还要继续服务。

(3)顾客等待模块,是一个判断等待条件是否成立的模块。

若c-w>0,则顾客具备等待条件,否则等待条件不成立,顾客离开。

 

T

F

F

T

F

T

 

图3.2主函数流程图

 

3.3创建数据结构

定义一个理发类,便于主程序调用。

加快进程调度,提高资源利用率,增大CPU吞吐量,减少内存空间。

减少进程等待时间,使得程序清晰可读,处理机调用高速快捷。

classlifa;

intc;//沙发数

intcustomers=0;//顾客数

intcount=0;//循环中用来计量的

intw=0;//等候理发的人数

intfinish=0;//已经理完发的人数

intwork1=0,work2=0,work3=0;//理发师是否在工作

charopendoor;//理发店是否开门接待顾客

intradom;//获取有无顾客数

4详细设计

定义一个lifa类,便于主函数调用。

线程lifa()和lifashi()是两个公有函数,定义私有变量ii用来对进程进行控制,ii<=0表示没有顾客,理发师处于休息状态。

ii>0表示理发店有顾客到来,对A、B、C三个理发师工作状态进行判断,若work==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控制营业开始的模块

这个功能的实现是用了一个循环,当询问是否开始营业是,用户有两个选择,一个是,一个否,当选择是时,输出“理发店开门营业!

”程序跳出该循环进入下一个功能;当选择否时,输出“对不起,理发店还没有开门”然后继续询问是否营业。

cout<<"是否营业?

y/n"<

cin>>opendoor;

while(opendoor!

='y')

{

cout<<"对不起,理发店还没有开门!

"<

cout<<"是否营业?

y/n"<

cin>>opendoor;

}

cout<

cout<<"理发店开门营业!

"<

cout<

4.2建立一个理发类

建立理发类的作用就是要在主函数中显得更简洁明了,不至于觉得繁琐。

使用更方便,也方便改动程序。

classlifa

{public:

lifa(inti){ii=i;}

voidlifashi();

private:

intii;

};

4.3理发功能模块

课程设计的主要目的是了解并且掌握进程之间的同步互斥,和进程之间的通信问题。

结合课本上的生产者与消费者问题可以从这方面来实现一个多进程的小系统,并且解决多个进程之间的通信,并发等问题,以此来达到课程设计的目的。

理发师问题是将顾客看做生产者,将理发师作为消费者。

设置一定数量的椅子的数目来作为缓存区的大小。

顾客来到的时候坐在椅子上,将自己作为“产品”,理发师理发的时候从椅子上叫走顾客,相当于消费“产品”,从而达到了课程设计要求的前一个要求。

顾客作为生产者,每到来一个就使计数器count增加1,以便让理发师理发(相当于消费)至最后一个顾客(相当于产品)。

并且,第1个到来的顾客应负责唤醒理发师;如果不是第1个到达的顾客,则在有空椅子的情况下坐下等待,否则离开理发店(该消息可由计数器count获得)。

这是理发类中定义的一个控制理发师理发的函数。

这里用了两个循环嵌套,中间小的一层是控制顾客来的数目,当有顾客来访,就开始往下执行,判断理发师是否有空,如果有空,就进行理发,若没有空,就判断是否有空闲沙发可以让顾客等待,若果有空闲沙发,则顾客等待,若没有空闲沙发,顾客就离开理发店。

理发完成就显示理发完成,完成数就加一,如果理发完成数大于三个人,就输出理发完成的状态和等待的顾客数。

询问是否继续理发,如果否,则退出程序,如果是,则先为等待的顾客理发,完成后输出已完成。

由于整个模块是由一个大的模块控制循环,所以你选择继续,则会又继续重复上面的功能,知道你选择退出程序。

主要有以下一些函数来实现整个问题的实现过程:

(1)用随机函数lifa()来产生进入理发店的顾客。

(2)定义理发师的理发函数lifashi()用来实现理发操作。

(3)定义一个lifa类用来实现顾客被理发的操作。

(4)用顾客线程customer实现对顾客行为的控制。

(5)用状态量work实现对理发师行为的控制。

(6)定义主函数main实现对两个线程的控制和执行操作。

 

 

F

T

 

T

F

F

T

 

F

T

 

图4.3理发师功能流程图

 

voidlifa:

:

lifashi()

{intc=3;//沙发数

intcustomers=0;//顾客数

intcount=0;//循环中用来计量的

intw=0;//等候理发的人数

intfinish=0;//已经理完发的人数

intwork1=0,work2=0,work3=0;//理发师是否在工作

charjixu,p;

while(ii<=0)

{cout<<"没有顾客来理发,理发师坐在沙发上休息"<

cout<<"请输入来的顾客数,输入0表示没有顾客来:

"<

cin>>ii;

}

while(ii>0)

{for(count=0;count<=2;count++)

{

customers++;

cout<<"第"<

"<

if(work1==1)//判断是否正为顾客理发,是则新来顾客等待,否则不用等待

{

if(w

{

cout<<"有"<

"<

w++;

}

else

cout<<"没有空沙发,顾客离开。

"<

}

else

{

cout<<"A理发师为第"<

"<

work1=1;

}

customers++;

cout<<"第"<

"<

if(work2==1)//判断是否正为顾客理发,是则新来顾客等待,否则不用等待

{

if(w

{

cout<<"有"<

"<

w++;

}

else

cout<<"没有空沙发,顾客离开。

"<

}

else

{

cout<<"B理发师为第"<

work2=1;

}

customers++;

cout<<"第"<

"<

if(work3==1)//判断是否正为顾客理发,是则新来顾客等待,否则不用等待

{

if(w

{

cout<<"有"<

"<

w++;

}

else

cout<<"没有空沙发,顾客离开。

"<

}

else

{

cout<<"C理发师为第"<

"<

work3=1;

}

}

if(work1==1)

{

cout<<"A理发完成。

"<

work1=0;//理发完成,理发师空闲

finish++;//理发完人数加1

}

if(work2==1)

{

cout<<"B理发完成。

"<

work2=0;//理发完成,理发师空闲

finish++;//理发完人数加1

}

if(work3==1)

{

cout<<"C理发完成。

"<

work3=0;//理发完成,理发师空闲

finish++;//理发完人数加

}

if(finish>2)//完成为3个人理发的任务,询问理发师是否继续工作

{

cout<<"已经为"<

y/n"<

cin>>jixu;

if(jixu=='n')

{cout<<"谢谢光临!

"<

exit(0);}

}

if(w>0)//看看是否有人在等待理发

{

cout<<"有"<

w--;

work1=1;//有则进入工作状态

if(w>0)//看看是否有人在等待理发

{

cout<<"有"<

w--;

work2=1;//有则进入工作状态

if(w>0)//看看是否有人在等待理发

{

cout<<"有"<

w--;

work3=1;//有则进入工作状态

}}}

if(work1==1)

{

cout<<"A将等待的顾客理发完成。

"<

work1=0;//理发完成,理发师空闲

finish++;//理发完人数加1

}

if(work2==1)

{

cout<<"B将等待的顾客理发完成。

"<

work2=0;//理发完成,理发师空闲

finish++;//理发完人数加1

}

if(work3==1)

{

cout<<"C将等待的顾客理发完成。

"<

work3=0;//理发完成,理发师空闲

finish++;//理发完人数加1

}

cout<<"已经为"<

y/n"<

cin>>p;

if(p=='y')

{jixu=p;}

if(p=='n')

{jixu=p;

cout<<"谢谢光临!

"<

exit(0);}

}

}

 

5系统实现原理

目的:

深入掌握进程调度的概念原理和实现方法。

调试要求:

编写一个进程调度程序,允许多个进程并行执行。

进程调度算法:

采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)、先来先服务算法、按时间片轮转调度算法,最终总结该算法的优缺点。

每个进程有一个进程控制块(PCB)表示,进程控制块可以包含如下信息:

进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等。

进程的优先数及需要的运行时间可以事先人为指定(也可以由随机数产生)。

进程的到达时间为输入进程的时间。

进程的运行时间以时间片为单位进行计算。

每个进程的状态可以是就绪W(wait)、运行R(run)或完成F(finish)三种状态之一。

如果运行下个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进行已占用CPU时间还未达到所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。

每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。

重复以上过程,直到所有进程都完成为止。

因为理发店的营业是持续的,在一个阶段完成后,怎么选择继续执行呢,这里我用了一个选择语句,然后利用循环不断地来完成这个过程。

在顾客接受服务的过程中,有很多判断条件,以保证顾客的分类,到底是接受服务,还是等待,又或者是离开。

这个功能是利用很多if语句来完成的。

这里用的类的调用,使得主函数变得简单,而在改动程序时也方便许多。

特点:

既照顾了短进程,又考虑了进程到达的先后次序,也不会使长进程长期得不到服务,因此是一个比较全面考虑的算法,但每次进行调度时,都需要对各个进程计算响应比。

所以系统开销很大,比较复杂。

原理:

每次调度是从就绪队列中,选择一个最先进入就绪队列的进程,把处理器分配给该进程,使之得到执行。

该进程一旦占有了处理器,它就一直运行下去,直到该进程完成或因发生事件而阻塞,才退出处理器。

特点:

利于长进程,而不利于短进程。

原理:

它是从就绪队列中选择一个估计运行时间最短的进程,将处理器分配给该进程,使之占有处理器并执行,直到该进程完成或因发生事件而阻塞,然后退出处理器,再重新调度。

原理:

它是从就绪队列中选择一个响应比最高的进程,让其获得处理器执行,直到该进程完成或因等待事件而退出处理器为止。

P原语操作如下:

<1>sem减1。

<2>若sem减1后仍大于零,则P原语返回,该进程继续执行。

<3>若sem减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度。

 

T

F

 

图5.4P原语操作功能图

 

V原语操作如下:

<1>sem加1。

<2>若sem加1后仍大于零,则V原语停止执行,该进程返回调用处,继续执行。

<3>若sem加1后小于或等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转进程调度。

 

F

T

 

图5.5V原语操作功能图

 

6程序运行界面

6.1进入程序友好界面

进入程序友好界面,程序初始化c=3,则输出“理发店内总共有3张沙发”给变量opendoor负值,以选择理发店是否开门。

图6.1友好界面

 

6.2理发店营业界面

若opendoor=“y”,则输出“理发店开门营业”ii的取值范围在1—9之间,输入0表示没有顾客上门,输入随机数表示顾客数。

图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设计总结

为期两个星期操作系统课程设计马上就要结束了,现在我来总结一下这两个星期所学的内容和感想。

课程设计对学生而言是其对所学课程内容掌握情况的一次自我验证,从而有着极其重要的意义。

通过课程设计能提高学生对所学知识的综合应用能力,能全面检查并掌握所学内容;《计算机操作系统》从课程性质上讲是一门专业基础课,它的目的和任务就是训练学生对计算机操作系统的认识,让学生对计算机操作系统有更进一部的认识,进而增加其对学习和应用相关专业课的兴趣。

通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,将结论用于实践,从而提高自己的实际动手能力和独立思考的能力。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 化学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1