1、武汉理工大学华夏学院 课程设计报告书 课程名称: 操作系统原理 题 目 : 用多线程同步方法解决哲学家就餐问题 系 名: 专业班级: 姓 名 : 学 号: 指导教师 : 2014 年 6 月 12 日 武汉理工大学华夏学院信息工程系 课 程 设 计 任 务 书 课程名称: 操作系统原理课程设计 指导教师 : 班级名称: 开课系、教研室: 软件与信息安全 一、课程设计目的与任务 操作系统课程设计是操作系统原理课程的后续实践课程,旨在通过一周的实践训练,加深学生对理论课程中操作系统概念,原理和方法的理解,加强学生综合运用操作系统原理、Linux 系统、 C 语言程序设计技术进行实际问题处理的能力,
2、进一步提高学生进行分析问 题和解决问题的能力,包含系统分析、系统设计、系统实现和系统测试的能力。 学生将在指导老师的指导下,完成从需求分析,系统设计,编码到测试的全过程。 二、课程设计的内容与基本要求 1、课程设计题目 用多线程同步方法解决哲学家就餐问题 2、课程设计内容 本课程设计要求在 Linux 操作系统, GCC 编译环境下开发。 用 c/c+语言在 Linux 操作系统环境下,通过研究 Linux 的线程机制和信号量实现哲学家就餐问题的并发控制。 为避免死锁,可采用只许 4 个哲学家入席且桌上有 5 支筷子的办法。几把椅子可用连续存储单元。 1 每个哲学家取得一双筷子开始用餐后,即时
3、显示“ Dining” 和该哲学家的标识符以及餐桌上有几位哲学家及其所坐的位置。 2 设定共有 10 个哲学家需用餐。每位用餐耗时 10 秒钟以上。 3 多个 哲学家 须共享操作函数代码。 提示 : 1 有界缓冲区 /连续存储区可用数组实现。 2 编译命令可用: gcc -lpthread -o 目标文件名 源文件名 3 多线程编程方法参见电子文档。 3、设计报告撰写格式要求: 1 设计题目与要求 2 设计思想 3 系统结构 4 数据结构的说 明和模块的算法流程图 5 使用说明书(即用户手册):内容包含如何登录、退出、读、写等操作说明 6 运行结果和结果分析(其中包括实验的检查结果、程序的运行
4、情况) 7 自我评价与总结 8 附录:程序清单,注意加注释(包括关键字、方法、变量等),在每个模块前加注释; 西南交通大学本科毕业设计(论文) 第 2 页 三、课程设计步骤及时间进度和场地安排 本课程设计将安排在第 17 周 , 教育技术中心。具体安排如下: 第一天,下发任务书,学生查阅资料 第二天,系统设计和原型开发 第三,四天 系统功能实现 第五天,系统调试 测试 打包和验收 周次 星期一 星期二 星期三 星期四 星期五 第 17 周 第 1-8 节 第 1-8 节 第 1-8 节 第 1-8 节 第 1-8 节 地点 现教 241 现教 241 现教 241 现教 241 现教 241
5、四、课程设计考核及评分标准 课程设计考核将综合考虑学生考勤和参与度,系统设计方案正确性,系统设计和开发效果以及课程设计报告书的质量。具体评分标准如下: 设置六个评分点 ( 1)设计方案正确,具有可行性、创新性; 25 分 ( 2)系统开发效果较好; 25 分 ( 3)态度认真、刻苦钻研、遵守纪律; 10 分 ( 4)设计报告规范、课程设计报告质量高、参考文献充分 20 分 ( 5)课程设计答辩概念清晰,内容正确 10 分 ( 6)课程设计期间的课堂考勤、答疑与统筹考虑。 10 分 按上述六项分别记分后求和,总分按五级记分法记载最后成绩。 优秀 ( 100 90分 ), 良好 ( 80 89分
6、), 中等 ( 70 79分 ), 及格 ( 60 69分 ), 不及格 ( 0 59 分 ) 西南交通大学本科毕业设计(论文) 第 3 页 1. 设计题目与要求 : 1.1. 用 多线程同步方法解决哲学家就餐问题 (Dining-Philosophers Problem) 1.2. 要求: 1.2.1. 每个哲学家取得一双筷子开始用餐后,即时显示“ Dining” 和该哲学家的标识符以及桌上有几位哲学家及其所坐的位置。 1.2.2. 设定共有 10 个哲学家需用餐。每位用餐耗时 10 秒钟以上。 1.2.3. 多个 哲学家 须共享操作函数代码。 2. 设计思想 : 2.1. 哲学家就餐问题,
7、即共有 5 个哲学家绕一个圆桌做在 5 个位置上,他们每 2 个人中间有一只筷子,共 5 只筷子,只有当每个哲学家取得他左右两边的筷子时,哲学家才能开始就餐,其它时间,哲学家只能思考或等待筷子。为 避免哲学家互相等待对方的筷子发生死锁,本次课程设计要求只许 4 个哲学家入席,以保证至少有一个哲学家能够进餐。 2.2. 本课程设计将 room 作为信号量,将其初始化为 4,以保证只允许 4 个哲学家同时入席就餐,这样就能保证至少有一个哲学家可以就餐。针对每个哲学家,通过共享操作函数代码,分别建立 5 个线程,以实现同步哲学家就餐,而申请进入餐厅的哲学家进入 room 的等待队列,根据 FIFO
8、的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象,针对 5 只筷子分别设置了 5 个互斥信号量,以保证每只筷子每次只能被取得一次。 3. 系统结构 : 一个桌子 ;五 个椅子 ;十 个 哲学家 ; 五支筷子 4. 数据结构的说明和模块的算法流程图 : 4.1. 线程创建函数 pthread_create 声明如下: #include int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 4.2. 1等待其它线程结束函数
9、pthread_join 声明如下: #include int pthread_join(pthread_t thread, void *retval); 4.3. 信号量的数据类型为结构 sem_t,它本质上是一个长整型的数。 桌子 椅子 椅子 椅子 椅子 哲学家 哲学家 哲学家 哲学家 哲学家 哲学家 哲学家 哲学家 哲学家 哲学家 筷子 筷子 筷子 筷子 筷子 椅子 西南交通大学本科毕业设计(论文) 第 4 页 初始化信号量函数 sem_init 声明如下: #include sem_init (sem_t *sem, int pshared, unsigned int value);
10、4.4. 增加信号量值函数 sem_post 声明如下: #include int sem_post(sem_t *sem); 4.5. 减少信号量值函数 sem_wait 声明如下 #include int sem_wait(sem_t * sem); 4.6. 主要数据结构声明: #define NUMBERS 10 /将哲学家人数 NUMBERS 定义为 10 sem_t chopsticsNUMBERS /定义 5 只筷子的互斥信号量 chopstics sem_t room /定义避免死锁的同步信号量 room 4.7. 线程共享函数 伪代码: void *Share(int i)
11、think(); p(room); /请求入席进餐 p(chopsticksetnumber); /请求左手边的筷子 p(chopsticksetnumber+1); /请求右手边的筷子 eat(); v (chopsticksetnumber); /释放左手边的筷子 v(chopsticksetnumber+1); /释放右手边的筷子 v(room); /退出席位释放信号量 chairs 西南交通大学本科毕业设计(论文) 第 5 页 流程图 开始 建立桌椅和上菜 设置哲学家 是否有座位? 等待 坐座位 左边是否有筷子? 等待 拿起左边的筷子 右边是否有筷子? 拿起右边的筷子 吃饭 哲学家 吃
12、完了 离开座位,一边画圈圈 结束 等待 Y Y Y N N N 西南交通大学本科毕业设计(论文) 第 6 页 5. 运行结果和结果分析 : 5.1. 运行结果 : rootlocalhost Desktop# gcc -lpthread -o a aaaa.c rootlocalhost Desktop# ./a 哲学家 1 坐上了位置 1 哲学家 1 拿到左侧筷子 1 哲学家 1 拿到右侧筷子 2 哲学家 1 坐在 1 椅子上吃饭 dining * 哲学家 1 坐在椅子 1 上 哲学家 2 坐上了位置 2 哲学家 3 坐上了位置 3 哲学家 3 拿到左侧筷子 3 哲学家 3 拿到右侧筷子 4
13、 哲学家 3 坐在 3 椅子上吃饭 dining * 哲学家 1 坐在椅子 1 上 哲学家 2 坐在椅子 2 上 哲学家 3 坐在椅子 3 上 西南交通大学本科毕业设计(论文) 第 7 页 哲学家 4 坐上了位置 4 哲学家 1 吃饱了放下筷子 1 和 2 哲学家 1 离开了位置 1 走到一边画圈圈 哲学家 3 吃饱了放下筷子 3 和 4 哲学家 3 离开了位置 3 走到一边画圈圈 哲学家 2 拿到左侧筷 子 2 哲学家 2 拿到右侧筷子 3 哲学家 2 坐在 2 椅子上吃饭 dining * 哲学家 2 坐在椅子 2 上 哲学家 5 坐上了位置 1 哲学家 5 拿到左侧筷子 1 哲学家 4
14、拿到左侧筷子 4 哲学家 4 拿到右侧筷子 5 哲学家 4 坐在 4 椅子上吃饭 dining * 哲学家 5 坐在椅子 1 上 哲学家 2 坐在椅子 2 上 哲学家 2 吃饱了放下筷子 2 和 3 哲学家 4 吃饱了放下筷子 4 和 5 哲学家 4 离开了位置 4 走到一边画圈圈 哲学家 5 拿到右侧筷 子 2 哲学家 5 坐在 1 椅子上吃饭 dining * 哲学家 5 坐在椅子 1 上 哲学家 2 坐在椅子 2 上 哲学家 6 坐上了位置 3 哲学家 6 拿到左侧筷子 3 哲学家 6 拿到右侧筷子 4 哲学家 6 坐在 3 椅子上吃饭 dining * 西南交通大学本科毕业设计(论文)
15、 第 8 页 哲学家 5 坐在椅子 1 上 哲学家 2 坐在椅子 2 上 哲学家 6 坐在椅子 3 上 哲学家 2 离开了位置 2 走到一边画圈圈 哲学家 8 坐上了位置 2 哲学家 9 坐上了位置 4 哲学家 5 吃饱了放下筷子 1 和 2 哲学家 5 离开了位置 1 走到一边画圈圈 哲学家 6 吃饱了放下筷子 3 和 4 哲学家 6 离开了位置 3 走到一边画圈圈 哲学家 8 拿到左侧筷子 2 哲学家 8 拿到右侧筷子 3 哲学家 8 坐在 2 椅子上吃饭 dining * 哲学家 8 坐在椅子 2 上 哲学家 7 坐上了位置 1 哲学家 7 拿到左侧筷子 1 哲学家 9 拿到左侧筷子 4
16、 哲学家 9 拿到右侧筷子 5 哲学家 9 坐在 4 椅子上吃饭 dining * 哲学家 7 坐在椅子 1 上 哲学家 8 坐在椅子 2 上 哲学家 8 吃饱了放下筷子 2 和 3 哲学家 7 拿到右侧筷子 2 哲学家 7 坐在 1 椅子上吃饭 dining * 哲学家 7 坐在椅子 1 上 哲学家 8 坐在椅子 2 上 哲学家 9 吃饱了放下筷子 4 和 5 西南交通大学本科毕业设计(论文) 第 9 页 哲学家 9 离开了位置 4 走到一边画圈圈 哲学家 8 离开了位置 2 走到一边画圈圈 哲学家 10 坐上了位置 3 哲学家 10 拿到左侧筷子 3 哲学家 10 拿到右侧筷子 4 哲学家
17、 10 坐在 3 椅子上吃饭 dining * 哲学家 7 坐在椅子 1 上 哲学家 10 坐在椅子 3 上 哲学家 7 吃饱了放下筷子 1 和 2 哲学家 7 离开了位置 1 走到一边画圈圈 哲学家 10 吃饱了放下筷子 3 和 4 哲学家 10 离开了位置 3 走到一边画圈圈 5.2. 结果分析: 各个哲学家(线程)完全独立自主运作 ,达到了预期的目标,拿筷子自然无冲突,吃饭也能正常运行,全程序没有一个哲学家饿死(线程不执行),或者是有哲学家在座位上却吃不到饭(死锁)的问题。所有的哲学家都可以去画圈圈(吃饱了之后去思考)。 6. 自我评价与总结 : 通过本次课程设计,我对哲学家就餐这一操作
18、系统经典问题有了进一步的了解,尤其是在设计进 程同步算法方面有了新的认识。通过亲自动手和查询资料,我知道了通过Linux 系统的线程机制和信号量控制来实现哲学家就餐问题的并发控制。在这次课程设计中,由于没有掌握好进程同步中的一些关键知识,导致在实际操作中遇到了很多问题,比如说对信号灯初始化,可以用 sem_init 函数来很好的实现,而不需要在定义的时候就进行初始化。在整个程序设计和完善中,遇到很多问题,有些是由于对知识不了解引起的,有些是由于粗心引起的。此次课程设计使我明白,在程序设计中,我们需要有一个清晰的整体结构,然后针对每个模块逐步实现其功能,在设计 中也需要有严谨和认真的态度,才会更好的完成一项任务。 7. 附录:程序清 单,注意加注释(包括关键字、方法、变量等),在每个模块前加注释 #include #include