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