Linux下信号量实现进程同步、互斥(生产者消费者问题)
来源:互联网 发布:语音随机聊天软件 编辑:程序博客网 时间:2024/05/23 20:42
操作系统分析的一个小实验
运用Linux平台下的进程间同步和互斥机制,设计实现一个生产者进程和一个消费者进程通过共享内存交换数据,并能达到以下要求:一个仓库可以存放K件物品。生产者每生产一件产品,将产品放入仓库,仓库满了就停止生产。消费者每次从仓库中去一件物品,然后进行消费,仓库空时就停止消费。
因为有生产者、消费者以及仓库,所以需要三个信号量:full、empty和mutex分别表示仓库的库存的同步信号量、仓库为空的同步信号量和正在对仓库进行操作的互斥信号量。其初值分别为0、仓库的容量(程序中使用MAX_BUFFRT_SIZE表示)和0。流程图如图所示。
生产者:p(empty) -> p(mutex) -> v(mutex) -> v(full)
消费者:
p(full) -> p(mutex) -> v(mutex) ->v(empty)
环境如下:Ubuntu14.04.3,gcc(4.8.2),codeblocks(13.12)
//copyright @Vista(njupt)
#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include <sys/stat.h>#include <stdio.h>#include <unistd.h>/*KEY 为申请信号量的键值,通过键值可以用于不同进程间的通信*/#define KEY (key_t)14010322/*仓库大小*/#define MAX_BUFFER_SIZE10/*union semun 常用于semctl的最后一个参数, 有的系统上sem.h已包含,可能会因为重复而报错, 如果报错请将其去除。*/union semun { int val; struct semid_ds *buf; ushort *array;};/*仓库,buffer数组用于存贮生产的商品编号(product) write用于记录生产者生产的下一个商品应存贮在仓库的位置 read用于记录消费者消费的下一个商品在仓库中的位置 很明显这是个循环队列,write、read分别为头尾指针*/typedef struct _tagShareBuffer{ int buffer[MAX_BUFFER_SIZE]; int writer; int reader;}SHAREBUFFER;static void p(int semid ,int semNum);static void v(int semid ,int semNum);int main(){ int shmid; //共享内存的id char* shmPtr; intsemid; //信号量指针 int product = 1; //产品编号,从1开始 SHAREBUFFER* pSharebuffer; //共享内存的指针 int i; /*申请信号量*/ if ((semid = semget(KEY,3,IPC_CREAT|0660)) == -1) { printf("semget error! \n"); return -1; } /*三个信号量的初始赋值*/ union semun arg[3]; arg[0].val = 1; //mutex(0) arg[1].val = MAX_BUFFER_SIZE; //empty(1) arg[2].val = 0; //full(2) for(i=0;i<3;i++) semctl(semid,i,SETVAL,arg[i]); /*显示三个信号量的初值*/ for(i=0;i<3;i++) printf("The semval(%d) = %d\n",i,semctl(semid,i,GETVAL,NULL)); /*申请共享内存*/ if ((shmid = shmget(IPC_PRIVATE,sizeof(SHAREBUFFER),0600)) < 0) { printf("shmget error!\n"); return -1; } if((shmPtr = (char*)shmat(shmid,0,0)) == (void*)-1) { printf("shmat error!\n"); return -1; } memset((void*)shmPtr,0,sizeof(SHAREBUFFER)); pSharebuffer = (SHAREBUFFER*)shmPtr; /*创建进程*/ pid_t pid = fork(); if (pid < 0){ printf("creat process error.\n"); return -1; } if (pid == 0){ /*子进程,消费者*/ while(1) { p(semid ,2);//P(full) p(semid ,0);//P(mutex) /*输出三个信号量的值和消费仓库中的产品编号以及位置*/ product = pSharebuffer->buffer[pSharebuffer->reader]; for(i=0;i<3;i++) printf("son:The semval(%d) = %d\n",i,semctl(semid,i,GETVAL,NULL)); printf("son:release the product from buffer[%d] = %d;\n",pSharebuffer->reader,product); /* reader++ */ pSharebuffer->reader = (pSharebuffer->reader + 1) % MAX_BUFFER_SIZE; v(semid ,0);//V(mutex) v(semid ,1); //V(empty) sleep(1); //调节消费速度 } } else { //父进程,生产者 while(1) { p(semid ,1);//P(empty) p(semid ,0);//P(mutex) /*输出三个信号量的值和生产仓库中的产品编号以及位置*/ pSharebuffer->buffer[pSharebuffer->writer] = product; for(i=0;i<3;i++) printf("parents:The semval(%d) = %d\n",i,semctl(semid,i,GETVAL,NULL)); printf("parents:Produced the product into buffer[%d] = %d;\n",pSharebuffer->writer,product); /* 产品编号++ */ product++; /* write++ */ pSharebuffer->writer = (pSharebuffer->writer + 1) % MAX_BUFFER_SIZE; v(semid ,0);//V(mutex) v(semid, 2); //V(full) sleep(1); //调节生产速度 } } return 0;}/* p操作 */void p(int semid ,int semNum){ struct sembuf sb; sb.sem_num = semNum; sb.sem_op = -1; sb.sem_flg = SEM_UNDO; semop(semid, &sb, 1);}/* v操作 */void v(int semid ,int semNum){ struct sembuf sb; sb.sem_num = semNum; sb.sem_op = 1; sb.sem_flg = SEM_UNDO; semop(semid, &sb, 1);}
参考文献:
http://blog.csdn.net/yaozhiyi/article/details/7561759
《Linux程序设计(第四版)》最后说一下,《Linux程序设计》这本书写的真不错,很值得学习。
博主还是菜鸟,有不对或需要改进的地方还请大牛们多多指教。
0 0
- Linux下信号量实现进程同步、互斥(生产者消费者问题)
- 生产者-消费者问题实现 (linux下C同步信号量和互斥信号量的应用)
- linux中的生产者和消费者问题--信号量 互斥 同步
- Linux下进程的同步互斥实例——生产者消费者
- 消费者-生产者问题---进程的实现信号量
- 进程同步问题-生产者消费者问题(linux semaphore实现)
- 信号量实现生产者消费者问题 window linux
- 操作系统学习笔记-信号量及PV操作与进程互斥和消费者生产者问题
- Posex信号量 实现进程间的同步(生产者&消费者)
- Linux平台下线程同步,实现“生产者消费者问题”
- Linux下进程之间信号量互斥、同步
- 进程间同步互斥经典问题(一)生产者-消费者问题
- GNU/Linux中解决多线程互斥同步问题(生产者消费者同步问题)
- Linux下生产者消费者问题详细分析(操作系统期中考试论文---并发程序的同步和互斥)
- 信号量实现生产者消费者问题
- 进程同步互斥经典题之消费者与生产者问题
- 进程同步-生产者消费者问题
- 进程同步-生产者消费者问题
- JAVA将图片(本地或者网络资源)转为Base64字符串
- redis伪集群搭建
- GIT常用命令集合
- 图片的类型匹配
- 创建maven modules工程
- Linux下信号量实现进程同步、互斥(生产者消费者问题)
- spring 的ioc原理
- 羊与车的问题
- jquery向后台传入json数据
- 软件开发流程基础常识
- ECMAScript6.0学习之第一篇--let学习
- Linux常用命令
- 用jsp写 不落地式的图片打包下载
- 加载webView 内存泄露 导致内存暴涨的几种解决方案