操作系统课程设计说明书 基于Linux的进程之间通信
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中北大学
操作系统课程设计
说明书
学院、系:软件学院
专业:软件工程
学生姓名:学号:
设计题目:基于Linux的进程之间通信
实现信号量通信机制(哲学家进餐)起迄日期: 2015年12月28日- 2016年1月8日
****:***
2015 年12月25日
1需求分析
1.1小组的拿到的任务是:
设计内容:
(1) 实现管道通信,要求见P183习题(3)。
(2) 实现信号量通信机制,要求见P191习题(3)。
(3) 实现消息缓冲通信机制,要求见P197习题。
(4) 实现共享内存区通信机制,要求见P201习题(2)。
要求:
(1) 用Linux中进程控制系统调用函数来创建进程(线程)。
(2) 输出进程通信时同步的说明信息。
1.2小组分工我拿到的题目是:(2) 实现信号量通信机制,要求见P191习题(3)。
1.3题目的要求如下:
1.3.1.哲学家进餐问题描述:
设有5个哲学家,共享一张放有5把椅子和5把叉子的圆桌,每人分得一把椅子。
哲学家们在肚子饥饿时才试图分两次从两边捡起两把叉子就餐。
条件:
1.每个人只有拿到两把叉子时,哲学家才能吃饭
2.如果叉子已在他人手上,则哲学家必须等到他人吃完后才能拿起叉子
3.任性的哲学家在自己未拿到两把叉子吃饭之前,绝不放下自己手中的叉子
1.3.2问题:
1.什么情况下5个哲学家全部都吃不上饭?
答:当5个哲学家每人手中都拿到了1把叉子(共5把),即不肯放下自己手中的叉子又想要得到左右邻居的叉子时,每个哲学家永远拿不到两把叉子,所有哲学家都在等待另一把叉子,就会导致这5个哲学家谁都吃不上饭。
也就是产生死锁后的情况。
2.编程实现没有人饿死(永远拿不到两个叉子)的算法。
答:程序请看代码实现。
分析:没有人饿死,就是不允许出现死锁的情况(5个哲学家每人1把叉子)
1.3.3解决死锁的方法有三种:
1.至多允许四位哲学家同时去拿左边的叉子,最终保证至少有一位哲学家能够进餐,并且在用毕时能释放出他用过的两只叉子,从而使更多哲学家能够进餐;
2.规定当哲学家的左右两只叉子均可用时,才允许他拿起叉子进餐;
3.规定奇数号的哲学家先拿他左边的叉子,然后再去拿他右边的叉子,而偶数号哲学家则相反。
五位哲学家都先竞争奇数号叉子,获得后再竞争偶数号叉子,最终总有一位哲学家会因为获得两只叉子而进餐。
1.3.4我采用的解决死锁问题的方法
我采用的解决死锁的方法是第二种,即在哲学家拿起叉子前先判断他左右邻居的情况,只要左右邻居中有一位正在进餐(叉子已经被邻居拿到,邻居进餐结束前自己无法获得其叉子),就不允许其拿起叉子进餐,这就可以预防死锁的情况发生。
1.4软件需要完成的功能:
按照题目要求,需要调用Linux操作系统函数使用信号量机制完成对哲学家进餐问题的求解,要求所有哲学家都能吃到食物,并且要防止哲学家在竞争叉子过程发生死锁。
程序应该包含如下功能:
1.哲学家思考功能:哲学家在进餐前和进餐后处于思考状态;
2.哲学家拿起叉子动能:哲学家进餐前需要拿起叉子,在这个过程中可能发生死锁,所以要在这个功能中编写防止死锁的方法;
3.哲学家进餐功能:哲学家拿起叉子后开始进餐;
4.哲学家放下叉子功能:哲学家用餐完毕,放下叉子,并通知其左右邻居;
5.执行P、V操作功能:由于要使用信号量机制,肯定会涉及到P、V操作
6.创建工作环境功能:包括建立共享内存区、连接进程和共享内存区、创建并初始化信号量集、创建子进程模拟5个哲学家等。
1.5软件设计的目的:
完成对哲学家进餐问题的求解,解决死锁问题。
1.6最终成果:
最终要提交的成果是:说明书、源程序(cpp文件)
2总体设计
2.1程序模块结构图:
图1 哲学家进餐问题程序模块结构图2.2程序流程图
2.2.1 总体流程图
开始
申请共享内存区
失败
申请是否成功
成功
连接共享内存区和进程
失败
连接是否成功
成功
创建信号量集并初始化信号量
创建N个子进程
失败
创建是否成功
成功
执行哲学家进餐问题解决方案
结束
图2 总体程序流程图
2.2.2哲学家进餐问题解决方案流程图
图3 哲学家进餐问题解决方案流程图
3.详细设计
3.1 包含必要的头文件
由于要调用Linux系统函数,所以要导入必要的头文件,需要导入的头文件如下:
3.2所有用到的常量、全局变量及宏定义
3.3联合体semun的定义
联合体semun用于在对信号量设置和修改值的时候作为semctl函数的最后一个参数。
3.4创建并初始化工作环境模块
3.4.1涉及到的Linux系统函数
在这个模块中,涉及到很多Linux系统函数的调用,以下是这些重要函数的解释:(1)shmget函数说明:
函数原型:int shmget(key_t key, size_t size, int shmflg)
函数作用:得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符。
参数含义:
key:0(IPC_PRIVATE):会建立新共享内存对象
大于0的32位整数:视参数shmflg来确定操作。
size:大于0的整数:新建的共享内存大小,以字节为单位
0:只获取共享内存时指定为0
shmflg:0:取共享内存标识符,若不存在则函数会报错
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符 IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错
返回值:成功:返回共享内存的标识符出错:-1,错误原因存于error中
(2)shmat函数说明:
函数原型:void *shmat(int shmid, const void *shmaddr, int shmflg)
函数作用:连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
参数含义:shmid 共享内存标识符
shmaddr 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg SHM_RDONLY:为只读模式,其他为读写模式
返回值:成功:附加好的共享内存地址出错:-1,错误原因存于errno中
(3)semget函数说明:
函数原型:int semget(key_t key,int nsems,int semflg);
函数作用:获取与某个键关联的信号量集标识
参数含义:key:所创建或打开信号量集的键值。
nsems:创建的信号量集中的信号量的个数,该参数只在创建信号量集时有效。
semflg:调用函数的操作类型
返回值:成功返回信号量集的IPC标识符,失败返回-1
(4)信号量操作模板sem_op定义:
struct sembuf{
unsigned short sem_num;
short sem_op;
short sem_flg;
};
当sem_op.sem_op为-1时表示执行P操作,sem_op为1时表示执行V操作
3.4.2申请共享内存区
3.4.3连接共享内存区和进程
3.4.4创建信号量集并初始化信号量
3.5 实现P、V操作
3.5.1涉及到的Linux系统函数
(1)semop函数说明:
函数原型:int semop(int semid, struct sembuf *sops, unsigned nsops); 函数作用:对信号量执行P、V操作
参数含义:semid:信号集的识别码,可通过semget获取(semget返回值)。
sops:信号量操作模板
nsops:信号操作结构的数量,恒大于或等于1
返回值含义:操作结果,正常返回值为0,错误返回-1
3.5.2实现P操作
3.5.3实现V操作
3.6实现哲学家进餐问题解决方案的主要算法3.6.1涉及到的linux系统函数
(1)sleep函数
函数原型:sleep(unsigned long);
函数作用:执行挂起一段时间
注意:sleep()单位为秒
3.6.2实现哲学家思考功能
3.6.2实现哲学家进餐功能
3.6.3实现哲学家拿起叉子功能
3.6.3.1实现拿起叉子前的试探操作(防止死锁算法)
3.6.3.2实现拿起叉子功能
3.6.4实现放下叉子功能
3.6.5将上述功能整合起来
3.7将所有模块连接在一起,形成一套完整的程序
为了方便最终的整合,将所有模块的整合调用放进一个单独的函数,供主函数调用,最终程序整合只需调用这个方法。
3.8编写主函数
3.9编写菜单
3.10运行结果
使用终端编译,结果如下:
4.心得体会
通过本次课程设计我学到了很多,下面谈一谈我的收获:
(1)团队合作方面:本次课程设计过程中由于我们分工明确,任务下达清楚,大家都知道自己该做什么,都朝着正确的方向在努力,所以收到了比较好的效果,效率也较高,这使我明白了,在以后的分工合作过程中,合理的分工和明确的任务的重要性。
(2)程序设计方面:本次课程设计过程中我遇到了很多挑战:
首先是来自题目的挑战,因为自己从来没用过Linux操作系统,所以看到题目后很担心自己会完不成任务,但是最后我还是下决心从0开始,网上的Linux版本花样繁多,不知道该选择那个号,历经很多次失败后,终于成功从网上下载了Red Hat Enterprise Linux 6版本并安装成功了程序的编译环境(gcc)和运行环境(Eclipse C++),并成功编译了Linux 上的第一个C++程序。
这次经历使我感受到了自学能力的重要性。
在如今的环境下,IT技术更新速度飞快,所以自学能力就显得尤为重要,这次自学安装配置Linux环境,编译自己写的源代码的过程中我感觉到Linux的用法和Mac OS X操作系统十分相似,很多操作是相通的,这也体现了知识之间是相互联系的,因为Linux和Mac OS X操作系统使用的都是UNIX 内核,所以有所相似很正常。
其次是来自技术方面的挑战,很多之前在windows上使用的语句在linux下也发生了改变,导致我在做菜单的时候很多操作都不起作用,这提醒了我以后要注意程序的可移植性。
这次课设对我的帮助很大,今后我会再接再厉,努力做好每份程序。