logo资料库

操作系统实验四 进程同步实验.doc

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
软件学院实验报告 实验题目:进程同步实验 1.实验目标: 加深对并发协作进程同步与互斥概念的理解,观察和体验并发进 程同步与互斥操作的效果,分析与研究经典进程同步与互斥问题的实 际解决方案。了解Linux系统中IPC进程同步工具的用法,练习并发协 作进程的同步与互斥操作的编程与调试技术。 2.实验环境 硬件环境: PC 软件环境:linux 4.源代码注释 1、生产者的代码如下: #include "ipc.h" int main(int argc,char *argv[]) { int rate; char *yl1[]={"烟草","纸","胶水"}; //可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度 if(argv[1] != NULL)
rate = atoi(argv[1]); else rate =3; //不指定为 3 秒 //共享内存使用的变量 buff_key = 101;//缓冲区任给的键值 buff_num = 2;//缓冲区任给的长度 pput_key = 102;//生产者放产品指针的键值 pput_num = 1; //指针数 shm_flg = IPC_CREAT | 0644;//共享内存读写权限 //获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址 buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg); //获取生产者放产品位置指针 pput_ptr pput_ptr = (int *)set_shm(pput_key,pput_num,shm_flg); //信号量使用的变量 prod_key = 203;//生产者同步信号灯键值 pmtx_key = 204;//生产者互斥信号灯键值 cons1_key = 307;//消费者 1 同步信号灯键值 cmtx1_key = 308;//消费者 1 互斥信号灯键值 cons2_key = 303;//消费者 2 同步信号灯键值 cmtx2_key = 304;//消费者 2 互斥信号灯键值 cons3_key = 305;//消费者 3 同步信号灯键值 cmtx3_key = 306;//消费者 3 互斥信号灯键值 sem_flg = IPC_CREAT | 0644;
//生产者同步信号灯初值设为缓冲区最大可用量 sem_val = 1; //获取生产者与消费者同步信号灯,引用标识存 prod_sem prod_sem = set_sem(prod_key,sem_val,sem_flg); //消费者初始无产品可取,同步信号灯初值设为 0 sem_val = 0; //获取消费者同步信号灯,引用标识存 cons_sem cons1_sem = set_sem(cons1_key,sem_val,sem_flg); cons2_sem = set_sem(cons2_key,sem_val,sem_flg); cons3_sem = set_sem(cons3_key,sem_val,sem_flg); //生产者互斥信号灯初值为 1 sem_val = 0; //获取生产者同步信号灯,引用标识存 pmtx_sem pmtx_sem = set_sem(pmtx_key,sem_val,sem_flg); //循环执行模拟生产者不断放产品 int u=0; while(1){ //如果缓冲区满则生产者阻塞 down(prod_sem); sleep(rate); int i=rand()%3+1; *pput_ptr=0;
buff_ptr[*pput_ptr]=i; printf("%d producer put: %s to Buffer[%d]\n",getpid(),yl1[i-1],*pput_ptr); up(pmtx_sem); //唤醒生产者 2 u=u+1; } return EXIT_SUCCESS; } 生产者 2 与生产者 1 不同之处: while(1){ //如果缓冲区满则生产者阻塞 //down(prod_sem); //如果另一生产者正在放产品,本生产者阻塞 down(pmtx_sem); *pput_ptr=0; int j=buff_ptr[*pput_ptr]; int i=j%3+1; *pput_ptr=1; buff_ptr[*pput_ptr]=i; if(i!=1&&j!=1){ //buff_ptr[*pput_ptr] = '1'; up(cons1_sem);
printf("%d producer put: %s to Buffer[%d]\n",getpid(),yl2[i-1],*pput_ptr); } if(i!=2&&j!=2){ //buff_ptr[*pput_ptr] = '2'; up(cons2_sem); printf("%d producer put: %s to Buffer[%d]\n",getpid(),yl2[i-1],*pput_ptr); } if(i!=3&&j!=3){ //buff_ptr[*pput_ptr] = '3'; up(cons3_sem);//唤醒消费者,唤醒哪个消费者由生产者生产的 产品决定(if) printf("%d producer put: %s to Buffer[%d]\n",getpid(),yl2[i-1],*pput_ptr); } sleep(rate); } 2、消费者的代码如下:(三个消费者代码相同,只是输出不同) #include "ipc.h" int main(int argc,char *argv[]) {
int rate; //可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度 if(argv[1] != NULL) rate = atoi(argv[1]); else rate = 3; //不指定为 3 秒 //共享内存 使用的变量 buff_key = 101; //缓冲区任给的键值 buff_num = 2; //缓冲区任给的长度 cget_key = 103; //消费者取产品指针的键值 cget_num = 1; //指针数 shm_flg = IPC_CREAT | 0644; //共享内存读写权限 //获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址 buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg); //获取消费者取产品指针,cget_ptr 指向索引地址 cget_ptr = (int *)set_shm(cget_key,cget_num,shm_flg); //信号量使用的变量 prod_key = 203; //生产者同步信号灯键值 pmtx_key = 204; //生产者互斥信号灯键值 cons1_key = 307; //消费者同步信号灯键值 cmtx1_key = 308; //消费者互斥信号灯键值 sem_flg = IPC_CREAT | 0644; //信号灯操作权限
//生产者同步信号灯初值设为缓冲区最大可用量 sem_val = 1; //获取生产者与消费者同步信号灯,引用标识存 prod_sem prod_sem = set_sem(prod_key,sem_val,sem_flg); //消费者初始无产品可取,同步信号灯初值设为 0 sem_val = 0; //获取消费者同步信号灯,引用标识存 cons_sem cons1_sem = set_sem(cons1_key,sem_val,sem_flg); //消费者互斥信号灯初值为 1 sem_val = 1; //获取消费者互斥信号灯,引用标识存 cmtx_sem cmtx1_sem = set_sem(cmtx1_key,sem_val,sem_flg); //循环执行模拟消费者不断取产品 while(1){ //如果无产品消费者阻塞 down(cons1_sem); //如果另一消费者正在取产品,本消费者阻塞 sleep(rate); printf("有烟草的抽烟者\n"); char *s="纸,胶水"; //用读一字符的形式模拟消费者取产品,报告本进程号和获取的字符 及读取的位置
printf("%d 有烟草的抽烟者得到: %s\n",getpid(),"纸,胶水"); up(prod_sem); } return EXIT_SUCCESS; } 5.调试及运行 1、 在终端里面输入 make 命令,执行编译和链接 2 打 开 多 个 标 签 页 并 分 别 输 入./producer1 ./producer2 ./consu1 ./consu2 ./consu3 运行程 序 , 运 行 结 果 如 下 图 所 示 :
分享到:
收藏