操作系统课程设计 理发师问题的实现

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

*******************

实践教学

*******************

兰州理工大学

计算机与通信学院

2011年秋季学期

操作系统课程设计

题目:理发师问题的实现

专业班级:计算机科学与技术

姓名:

学号:

指导教师:

成绩:

摘要

理发师问题是一个利用信号量进行PV操作的经典问题。设计程序实现此问题,要使得理发师的活动与顾客的活动得到各自真实的模拟。所执行的程序应体现:理发师在没有顾客的时候去睡觉,有顾客则工作;顾客在理发师工作时坐下等待,无座时离开,直至等到理发师自己理发。

关键字:理发师,顾客,PV操作。

目录

摘要 (2)

1 设计要求 (4)

1.1初始条件 (4)

1.2技术要求 (4)

2 总体设计思想及开发环境与工具 (4)

2.1 总体设计思想 (4)

2.2 多线程编程原理 (5)

2.2.1 创建一个线程 (5)

2.2.2 等待一个线程结束 (5)

2.2.3 信号量 (6)

2.3 伪码实现 (6)

2.4 开发环境与工具 (8)

3数据结构与模块说明 (8)

3.1 数据结构 (8)

3.2函数的调用关系图 (8)

3.2.1主函数模块 (8)

3.2.2 理发师模块 (9)

3.2.3 顾客模块 (10)

5运行结果 (10)

5.1运行步骤 (10)

5.2测试结果 (11)

5.2.1 编辑,编译和运行的过程图 (11)

5.2.2 错误部分截图 (12)

5.2.3 正确运行结果图 (12)

设计总结 (16)

参考文献 (17)

致谢 (18)

附录(源程序代码) (19)

1 设计要求

1.1初始条件

(1)操作系统:Linux

(2)程序设计语言:C语言

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

1.2技术要求

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

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

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

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

2 总体设计思想及开发环境与工具

2.1 总体设计思想

题目中要求描述理发师和顾客的行为,因此需要两类线程barber()和customer ()分别描述理发师和顾客的行为。其中,理发师有活动有理发和睡觉两个事件;等待和理发二个事件。店里有固定的椅子数,上面坐着等待的顾客,顾客在到来这个事件时,需判断有没有空闲的椅子,理发师决定要理发或睡觉时,也要判断椅子上有没有顾客。所以,顾客和理发师之间的关系表现为:(1)理发师和顾客之间同步关系:当理发师睡觉时顾客近来需要唤醒理发师为其理发,当有顾客时理发师为其理发,没有的时候理发师睡觉。

(2)理发师和顾客之间互斥关系:由于每次理发师只能为一个人理发,且可

供等侯的椅子有限只有n把,即理发师和椅子是临界资源,所以顾客之间是互斥的关系。

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

ⅰ控制变量waiting用来记录等候理发的顾客数,初值为0;

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

ⅲ信号量barbers用来记录正在等候顾客的理发师数,并用作阻塞顾客进程,初值为1;ⅳ信号量mutex用于互斥,初值为1

2.2 多线程编程原理

此次在Linux下进行多线程编程需要用到pthread_create和pthread_join这两个函数。

2.2.1 创建一个线程

pthread_create用来创建一个线程,原型为:

extern int pthread_create((pthread_t *__thread, __const pthread_attr_t *__attr,void *(*__start_routine) (void *), void *__arg))

第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。函数thread不需要参数时,最后一个参数设为空指针。第二个参数设为空指针时,将生成默认属性的线程。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。

2.2.2 等待一个线程结束

pthread_join用来等待一个线程的结束,函数原型为:

extern int pthread_join __P ((pthread_t __th, void **__thread_return));

第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它

可以用来存

储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被

等待的线程结束为止,当函数返回时,被等待线程的资源被收回。

2.2.3 信号量

(1)函数sem_init()用来初始化一个信号量,函数原型为:

extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));

sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。(2)函数sem_post( sem_t *sem )用来增加信号量的值。

当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。

(3)函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。

2.3 伪码实现

difine n 5; //为顾客准备的椅子数为5

semaphore mutex=1; //用于互斥

semaphore customers=0;//等候理发的顾客数

semaphore barbers=1;//正在等候顾客的理发师数

int waiting=0; //等候理发的顾客数

//理发师线程

void barber()

{

相关文档
最新文档