编制模拟“五个哲学家”问题的程序
一.实验目的
学习和掌握并发进程同步的概念和方法。
二.实验要求
1、程序语法
philosopher [ -t <time> ]
<time>是哲学家进餐和沉思的持续时间值,缺省值为2秒。
2、五个哲学家的编号为0~4,分别用五个进程独立模拟。
3、程序的输出要简洁,仅输出每个哲学家进餐和沉思的信息。例如,当编号为3的哲学家在进餐时,就打印:
philosopher 3 is eating
而当他在沉思时,则打印:
philosopher 3 is thinking
除此之外不要输出其他任何信息。
4、利用课堂已教授的知识而不使用线程或IPC机制进行同步。
5、程序应该一直运行,直到人为地终止它(如按Ctrl-C或Ctrl-\)。不允许出现僵尸进程。
三.实验代码
#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include"apue.h" enum state{eat,think}; int count=0; int time=2; struct person{ int id; int pid; int sta; }pho[5]; int pid[5]; void print(int id,int i) { if(i==0) printf("philosopher %d is eating;\n",id); if(i==1) printf("philosopher %d is thinking;\n",id); } char *file[5]={"chopstick1.c","chopstick2.c","chopstick3.c","chopstick4.c","chopstick5.c"}; void chopstick(void){ int i; int fd; for(i=0;i<5;i++) unlink(file[i]); } void EatOrThink(int id) { int i,j; int fd; while(1){ if(id%2==0){ i=(id)%5; if((fd=open(file[i],O_RDONLY|O_CREAT|O_EXCL,FILE_MODE))<0) { pho[id].sta=think; print(id,think); sleep(time); } else { j=(id+1)%5; if((fd=open(file[j],O_RDONLY|O_CREAT|O_EXCL,FILE_MODE))<0) { unlink(file[i]); pho[id].sta=think; print(id,think); sleep(time); } else { pho[id].sta=eat; print(id,eat); sleep(time); unlink(file[j]); unlink(file[i]); sleep(time); } } } else { j=(id+1)%5; if((fd=open(file[j],O_RDONLY|O_CREAT|O_EXCL,FILE_MODE))<0) { pho[id].sta=think; print(id,think); sleep(time); } else { i=(id)%5; if((fd=open(file[i],O_RDONLY|O_CREAT|O_EXCL,FILE_MODE))<0) { unlink(file[j]); pho[id].sta=think; print(id,think); sleep(time); } else { pho[id].sta=eat; print(id,eat); sleep(time); unlink(file[i]); unlink(file[j]); sleep(time); } } } } } int main(int argc,char *argv[]) { if(argc==3) { time=atoi(argv[2]); printf("time=%d\n",time); } chopstick(); if((pid[0]=fork())<0) err_sys("wait error"); else if(pid[0]==0) { pho[0].id=0; pho[0].pid=getpid(); pho[0].sta=think; EatOrThink(pho[0].id); } if((pid[1]=fork())<0) err_sys("wait error"); else if(pid[1]==0) { pho[1].id=1; pho[1].pid=getpid(); pho[1].sta=think; EatOrThink(pho[1].id); } if((pid[2]=fork())<0) err_sys("wait error"); else if(pid[2]==0) { pho[2].id=2; pho[2].pid=getpid(); pho[2].sta=think; EatOrThink(pho[2].id); } if((pid[3]=fork())<0) err_sys("wait error"); else if(pid[3]==0) { pho[3].id=3; pho[3].pid=getpid(); pho[3].sta=think; EatOrThink(pho[3].id); } if((pid[4]=fork())<0) err_sys("wait error"); else if(pid[4]==0) { pho[4].id=4; pho[4].pid=getpid(); pho[4].sta=think; EatOrThink(pho[4].id); } wait(NULL); }
四.实验结果:
1.编译原文件:hilosopher.c,输入:gcc philosopher.c error2e.c -o philosopher,得到可执行程序philosopher.
2.实验结果
执行./philosopher,直到按Ctrl-C或Ctrl-\时结束。
对于无带时间的默认其缺省的时间为2秒
而对于带时间的函数
例如: ./philosopher –t 5
持续时间值为5.输出:
实验说明
1.在main函数中,首先应当先判断arge[]中的参数,如果没有时间,则将调用缺省时间为2秒。
2. if((pid[0]=fork())<0)
err_sys("wait error");
else if(pid[0]==0){
pho[0].id=0;
pho[0].pid=getpid();
pho[0].sta=think;
EatOrThink(pho[0].id);
}
分别设定各个哲学家的eating与thinking的值,再调用相应的函数进行区别,当然,在函数的编写过程当中,应当尽量避免函数中五个哲学家同时僵尸,而使程序出错。