您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 实验二进程同步实验综述
实验二进程同步一、实验目的:掌握基本的同步算法,理解经典进程同步问题的本质;学习使用Linux的进程同步机制,掌握相关API的使用方法;能利用信号量机制,采用多种同步算法实现不会发生死锁的哲学家进餐程序。二、实验平台:虚拟机:VMWare9以上操作系统:Ubuntu12.04以上编辑器:Gedit|Vim编译器:Gcc三、实验内容:(1)以哲学家进餐模型为依据,在Linux控制台环境下创建5个进程,用semget函数创建一个信号量集(5个信号量,初值为1),模拟哲学家的思考和进餐行为:每一位哲学家饥饿时,先拿起左手筷子,再拿起右手筷子;筷子是临界资源,为每一支筷子定义1个互斥信号量;想拿到筷子需要先对信号量做P操作,使用完释放筷子对信号量做V操作。伪代码描述:semaphorechopstick[5]={1,1,1,1,1};•第i位哲学家的活动可描述为:do{printf(%disthinking\n,i);printf(%dishungry\n,i);wait(chopstick[i]);//拿左筷子wait(chopstick[(i+1)%5]);//拿右筷子printf(%diseating\n,i);signal(chopstick[i]);//放左筷子signal(chopstick[(i+1)%5]);//放右筷子…}while[true];运行该组进程,观察进程是否能一直运行下去,若停滞则发生了什么现象?并分析原因。(2)解决哲学家进餐问题可采用如下方法:a.仅当哲学家的左、右两只筷子均可用时,才允许他拿起筷子进餐;b.至多只允许有4位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐;c.规定奇数号哲学家先拿起他左手的筷子,然后再拿起他右手的筷子,而偶数号哲学家则先拿起他右手的筷子,然后再拿起他左手的筷子。方法a在示例程序中给出,请用方法b和c写出不会发生死锁的哲学家进餐程序。(3)设计程序,实现生产者/消费者进程(线程)的同步与互斥。在该程序中创建4个进程(或线程)模拟生产者和消费者,实现进程(线程)的同步与互斥。实验结果:使用a方法结果哲学家就餐问题使用b方法解决哲学家就餐问题源码如下:#includestdio.h#includestdlib.h#includestring.h#includestdint.h#includestdbool.h#includeerrno.h#includeunistd.h#includesys/types.h#includesys/stat.h#includesys/ipc.h#includesys/sem.h#includesys/wait.hunionsemun{intval;structsemid_ds*buf;unsignedshort*array;structseminfo*_buf;};#defineERR_EXIT(m)\do{\perror(m);\exit(EXIT_FAILURE);\}while(0)//获取互斥信号量voidwait_mutex(intmutex){structsembufsb={0,-1,0};semop(mutex,&sb,1);//对互斥信号量进行操作}//取得筷子voidwait_v(intsemid,intnum){structsembufsb={num,-1,0};semop(semid,&sb,1);}//释放筷子voidsignal_p(intsemid,intnum){structsembufsb={num,1,0};semop(semid,&sb,1);}//释放互斥变量mutexvoidsignal_mutex(intsemid0){structsembufsb={0,1,0};semop(semid0,&sb,1);}//ph函数voidph(intnum,intsemid,intsemid0){intleft=num;intright=(num+1)%5;for(;;){printf(%disthinking\n,num);sleep(1);printf(%dishungry\n,num);sleep(1);//wait操作,控制哲学家最多4人能进餐wait_mutex(semid0);wait_v(semid,left);wait_v(semid,right);printf(%diseating\n,num);sleep(1);//signal操作signal_p(semid,right);//释放右筷子signal_p(semid,left);//释放左快子signal_mutex(semid0);//释放互斥信号量}}//主函数intmain(intargc,char*argv[]){intsemid,semid0;//创建两个信号量集semid0=semget(IPC_PRIVATE,1,IPC_CREAT|0666);semid=semget(IPC_PRIVATE,5,IPC_CREAT|0666);//unionsemunsu;su.val=1;inti;for(i=0;i5;i++){//semctl()系统调用在一个信号量集(或集合中的单个信号量)上执行各种控制操作semctl(semid,i,SETVAL,su);}//设定semid0信号量的初始值unionsemunsu0;su0.val=4;semctl(semid0,0,SETVAL,su0);//创建4个子进程intnum=0;pid_tpid;for(i=1;i5;i++){pid=fork();if(pid0){ERR_EXIT(fork);}if(pid==0){num=i;break;}}//第num个哲学家要做的事ph(num,semid,semid0);return0;}执行结果使用c方法解决哲学家就餐问题#includestdio.h#includestdlib.h#includestring.h#includestdint.h#includestdbool.h#includeerrno.h#includeunistd.h#includesys/types.h#includesys/stat.h#includesys/ipc.h#includesys/sem.h#includesys/wait.hunionsemun{intval;structsemid_ds*buf;unsignedshort*array;structseminfo*__buf;};#defineERR_EXIT(m)\do{\perror(m);\exit(EXIT_FAILURE);\}while(0)//取得筷子voidwait_v(intsemid,intnum){structsembufsb={num,-1,0};semop(num,&sb,1);}//释放筷子voidsignal_p(intsemid,intnum){structsembufsb={num,-1,0};semop(num,&sb,1);}//科学家要做的事voidph(intsemid,intnum){for(;;)//死循环{//判断哲学家的编号是奇数还是偶数//奇数先申请左边的筷子,偶数先申请右边的筷子if(num%2!=0){//判断奇数printf(%disthinking\n,num);sleep(1);printf(%dishungry\n,num);sleep(1);//wait操作wait_v(semid,num);wait_v(semid,(num+1)%5);printf(%diseating\n,num);sleep(1);//signal操作signal_p(semid,(num+1)%5);signal_p(semid,num);}if(num%2==0){//判断偶数printf(%disthinking\n,num);sleep(1);printf(%dishungry\n,num);sleep(1);//wait操作wait_v(semid,(num+1)%5);wait_v(semid,num);//signal操作signal_p(semid,num);signal_p(semid,(num+1)%5);}}}intmain(intargc,char*argv[]){intsemid;//创建5个信号量semid=semget(IPC_PRIVATE,5,IPC_CREAT|0666);unionsemunsu;su.val=1;inti;for(i=0;i5;i++){//注意第二个参数也是索引semctl(semid,i,SETVAL,su);}//创建4个子进程pid_tpid;intnum=5;for(i=0;i4;i++){pid=fork();if(pid0){ERR_EXIT(fork);}if(pid==0){num=i;break;}}//哲学家要做的事ph(semid,num);return0;}生产者和消费者的同步与互斥源代码如下:#includestdio.h#includestdlib.h#includeunistd.h#includepthread.h#includesemaphore.h#defineN2//消费者或者生产者的数目#defineM10//缓冲数目intin=0;//生产者放置产品的位置intout=0;//消费者取产品的位置intbuff[M]={0};//缓冲初始化为0,开始时没有产品sem_tempty_sem;//同步信号量,当满了时阻止生产者放产品sem_tfull_sem;//同步信号量,当没产品时阻止消费者消费pthread_mutex_tmutex;//互斥信号量,一次只有一个线程访问缓冲intproduct_id=0;//生产者idintprochase_id=0;//消费者id/*打印缓冲情况*/voidprint(){inti;for(i=0;iM;i++)printf(%d,buff[i]);printf(\n);}/*生产者方法*/void*product(){intid=++product_id;while(1){//用sleep的数量可以调节生产和消费的速度,便于观察sleep(1);//sleep(1);sem_wait(&empty_sem);pthread_mutex_lock(&mutex);in=in%M;printf(product%din%d.like:\t,id,in);buff[in]=1;print();++in;pthread_mutex_unlock(&mutex);sem_post(&full_sem);}}/*消费者方法*/void*prochase(){intid=++prochase_id;while(1){//用sleep的数量可以调节生产和消费的速度,便于观察sleep(1);//sleep(1);sem_wait(&full_sem);pthread_mutex_lock(&mutex);out=out%M;printf(prochase%din%d.like:\t,id,out);buff[out]=0;print();++out;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);}}intmain(){pthread_tid1[N];pthread_tid2[N];inti;intret[N];//初始化同步信号量intini1=sem_init(&empty_sem,0,M);intini2=sem_init(&full_sem,0,0);if(ini1&&ini2!=0){printf(seminitfaile
本文标题:实验二进程同步实验综述
链接地址:https://www.777doc.com/doc-5210746 .html