ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:767.01KB ,
资源ID:21122427      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/21122427.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(利用信号量机制解决哲学家进餐问题Word文档格式.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

利用信号量机制解决哲学家进餐问题Word文档格式.docx

1、哲学家的生活中有两种交替活动时段,吃饭(EATING)和思考(THINKING)。当一个哲学家觉得饿了时,他就试图分两次去取左手边和右手边的叉子,每次拿一把,但不分次序。如果成功拿到两把叉子,就进入吃饭状态,吃完后放下叉子继续思考。二、设计思路1.每个哲学家的行为活动状态为两种:进餐(EATING)和思考(THINKING)。因此创建一个有5个元素的状态数组,每个数组元素的状态值为EATING或者THINKING。2.五个哲学家围坐成一圈,每两个人中间有一个叉子,即每个哲学家的边和右边有一个叉子,但这个叉子需要和旁边的邻居竞争使用。对于每一个哲学家来说,其只有成功获得两个叉子,才能进入进餐状态

2、。在进完餐后,需要成功放下手中的两个叉子,才能进入思考的状态。换个角度的描述就是,每个哲学家查询左右边的邻居当前状态,如果左右的邻居当前状态都为THINKING,则该哲学家可以进餐;如果左右邻居当前状态不都是THINKING,则哲学家不能进餐。因此可以为每一个哲学家设置一个信号量,来描述哲学家的活动状态。3.因为五只叉子做多只能允许两个哲学家进餐,所以可以将桌子作为一个临界资源。通过设置一个互斥信号量来限制对临界资源的访问数。4.创建两个动作函数,对应于每个哲学家的获取两把叉子和放下两把叉子的动作。而每个动作都需要对互斥信号量和哲学家信号量进行访问操作,因此创建原子操作P和原子操作V,来执行对

3、信号量的消耗和释放操作。5.利用父进程创建五个子进程来模拟五个哲学家,在每个子进程中执行PHILOSOPHER(phi_num)函数来模拟每个哲学家进入哲学家进餐问题活动。三、主要问题的解决方法和关键技术1.共享状态数组问题。问题描述:因为状态数组是共享的,而每个模拟哲学家的子进程是相互独立的,有自己的地址空间,在进程之间共享使用状态数组出现问题。解决方法:父进程通过利用UNIX系统进程通信机制中共享内存机制的shmget()和shmat系统调用创建一个共享内存区,并将状态数组地址链接到进程地址空间,成功的解决了该问题。2.信号量创建及初始化问题整个程序使用两个不同的信号量,一个是记录型信号量

4、数组,一个是互斥信号量,并且在信号量创建初就需要对信号量进行初始化,这样才能保证接下来的子进程运行时,五个子进程面对的是相同值的信号量数组。父进程通过利用UNIX系统进程通信机制中信号量机制的semget()系统调用和semctl()系统调用,成功创建一个五元素的信号量数组和一个元素的信号量数组,并将其在初始为设计的初始值,保证了程序后续操作的正确。3.P和V原子操作问题在子进程中的对信号量的操作必须是原子操作P和V,而且由于在动作函数中需要调用P和V原子操作,所以必须保证P和V操作的原子性,否则函数之间参数的传递将出现不一致。利用UNIX系统进程通信机制中信号量机制的semop()系统调用,

5、封装P和V操作函数,保证了函数的原子性。4.进程创建的准确时刻问题根据设计的描述,程序是通过五个子进程来模拟五个哲学家,但对进程创建的先后顺序没有要求,又由于进程分配到时间片是有限的,并且在创建的过程中要保证五个子进程都是统一父进程创建的,所以对于进程的创建时刻不太容易确定。利用的UNIX系统的进程创建fork()系统调用,创建一个有五个子进程的进程扇,成功的解决创建准确时刻问题 5.哲学家动作函数编译问题 问题描述:在哲学家的三个动作函数中需要对两个类型的信号量进行操作,所以不可避免的需要调用P和V原子操作。尽管在动作函数定义之前,已经声明了P和V函数。但是由于其原子性,在动作函数中直接使用

6、P,V函数导致了严重的编译错误问题。 解决方法:通过在各个函数参数列表中添加需要指向将使用的P和V函数指针,并在使用时采用(*P)和(*V)形式来解除引用操作,成功的解决了编译错误问题。四、程序流程图约定: Take_forks 函数动作 TKFK Put_forks 函数动作 PTFK Test 函数动作 TEST THINKING 思考状态 THINK EATING 进餐状态 EAT N Y Y N五、原程序清单#includeunistd.hassert.hsys/types.hsys/ipc.hsys/sem.hsys/shm.hsignal.hstdlib.h#define N 5#

7、define LEFT(i) (i+N-1)%N#define RIGHT(i) (i+1)%N#define THINKING 0#define EATING 1/#includebehavior_philosophy.hvoid philosopher(int , char*, int , int , void (*)(int, int), void (*)(int, int);void take_forks(int , char* , int , int ,void (*)(int, int), void (*)(int, int);void put_forks(int , char*

8、, int , int ,void (*)(int, int), void (*)(int, int);void test(int , char* , int ,void (*)(int, int);void think(int );void eat(int );void P(int , int );void V(int , int );/*-哲学家动作-*/void philosopher(int i, char* state, int sem_phiid, int sem_mutexid, void (*P)(int, int), void (*V)(int, int) sleep(1);

9、 think(i); while(1) take_forks(i, state, sem_phiid, sem_mutexid, P, V); eat(i); put_forks(i, state, sem_phiid, sem_mutexid, P, V); void take_forks(int i, char* state, int sem_phiid, int sem_mutexid, void (*P)(int, int) , void (*V)(int, int) (*P)(sem_mutexid, 0); statei = THINKING; test(i, state, sem

10、_phiid, V); (*V)(sem_mutexid, 0); (*P)(sem_phiid, i);void put_forks(int i, char* state, int sem_phiid, int sem_mutexid,void (*P)(int, int), void (*V)(int, int) test(LEFT(i), state, sem_phiid, V); test(RIGHT(i), state, sem_phiid, V);void test(int i, char* state, int sem_phiid,void (*V)(int, int) if(s

11、tatei = THINKING & stateLEFT(i) != EATING & stateRIGHT(i)!=EATING) statei = EATING; (*V)(sem_phiid, i);void think(int i) printf(philosopher:%dis THINKING.n, i);void eat(int i)Im philosopher:is EATING.and will eating %d seconds!n, i, sleep(2);/*-P,V原子操作-*/void P(int semid, int index) struct sembuf se

12、ma_buffer; sema_buffer.sem_num = index; sema_buffer.sem_op = -1; sema_buffer.sem_flg = SEM_UNDO; semop(semid, &sema_buffer, 1);void V(int semid, int index) struct sembuf sema_buf; sema_buf.sem_num = index; sema_buf.sem_op = 1; sema_buf.sem_flg = SEM_UNDO;sema_buf, 1);/*-*/int main( )/*-创建信号量操作-*/int

13、 sem_phiid;sem_phiid = semget(1008, 5, 0666|IPC_CREAT);assert(sem_phiid=0);unsigned short array5 = 0, 0, 0, 0, 0;union semunint val;unsigned short *array;semopts;semopts.array=array;int ret1 = semctl(sem_phiid, 0, SETALL, semopts);assert(ret1 = 0);int sem_mutexid;sem_mutexid = semget(0x225, 1, 0666|

14、IPC_CREAT);assert(sem_mutexid = 0);semopts.val = 1;int ret2 = semctl(sem_mutexid, 0, SETVAL, semopts);assert(ret2 = 0);/*-初始化共享内存-*/int shmid;char* state;if(shmid = shmget(IPC_PRIVATE, N, 0600|IPC_CREAT) = -1) semctl(sem_phiid, 0, IPC_RMID, 0); semctl(sem_mutexid, 0, IPC_RMID, 0); perror(shmget fail

15、d!); exit(1);if(state = shmat(shmid, 0, 0) = (char *)-1)shmat faild!/*-*/ int i, phinum; pid_t pid; for(i=0; i0) while(wait(int *)0) = -1); semctl(sem_mutexid, 0, IPC_RMID, 0); shmdt(state);Hi, GAME OVER!else philosopher(phinum, state, sem_phiid, sem_mutexid, P, V);六、程序运行结果 截图一 截图二 截图三七、设计总结这次课程设计通过利用UNIX系统的信号量机制和共享内存机制,编写一个解决哲学家进餐问题的程序,感觉有很多收获,主要体现在以下几点:(1)很好的复习了UNIX系统编程课上所学的知识,尤其是对unix进程通信机制中信号量机制和共享内存机制有了实践和更深的认识。(2)练习了C编程,尤其是对函数指针有了更深的认识。(3)复习了操作系统进程通信的原理。

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

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