OS: 生产者消费者问题(二) ---- 系统V IPC通信-信号量和共享内存
在上一篇“OS: 生产者消费者问题(多进程+共享内存+信号量)”中提到的方法二: 如果进程之间并没有父子关系,但是协商好了共享存储的 KEY , 那么在每个进程中,就可以通过 KEY 以及 shmget 函数获得共享存储的 I D , 进而通过 shmat 函数获得共享存储的实际地址,最后访问。
本文采用此种方式进行同步生产者和消费者。
1、头文件myshm.h: 要用到的定义和说明
/* * myshm.h * * Created on: Aug 3, 2013 * Author: root */ #ifndef MYSHM_H_ #define MYSHM_H_ #endif /* MYSHM_H_ */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <stdio.h> #include <string.h> #define SHMSZ 256 union semun{ int val; struct semid_ds * buf; unsigned short * array; }; void init_a_semaphore(int sid, int semnum, int initval){ union semun semopts; semopts.val = initval; semctl(sid, semnum, SETVAL, semopts); } int semaphore_P(int sem_id){ struct sembuf sb; sb.sem_num=0; sb.sem_op = -1; sb.sem_flg = SEM_UNDO; if(semop(sem_id, &sb, 1) == -1){ printf("semaphore_P failed.\n"); return 0; } return 1; } int semaphore_V(int sem_id){ struct sembuf sb; sb.sem_num=0; sb.sem_op = 1; sb.sem_flg=SEM_UNDO; if(semop(sem_id, &sb, 1) == -1){ printf("semaphore_V failed.\n"); return 0; } return 1; }
2、生产者程序productProcess.c:
#include "myshm.h" int main(){ char * shm, *s; int shmid; int producer, consumer, i; char readbuf[SHMSZ]; if((consumer = semget((key_t)1234, 1, IPC_CREAT|0660)) == -1){ printf("server consumer semget failed.\n"); exit(1); } init_a_semaphore(consumer, 0, 0); if((producer = semget((key_t)5678, 1, IPC_CREAT|0660)) == -1){ printf("server producer semget failed.\n"); exit(1); } ///printf("ftok(\"consumer\", 0) = %d", (key_t)1234); //printf("ftok(\"consumer\", 0) = %d", (key_t)5678); //printf("ftok(\"consumer\", 0) = %d", ftok("consumer", 0)); //printf("ftok(\"producer\", 0) = %d", ftok("producer", 0)); init_a_semaphore(producer, 0, 1); if((shmid = shmget(ftok("shared",0), SHMSZ, 0666| IPC_CREAT)) == -1){ printf("server shmget failed.\n"); exit(1); } if((shm = shmat(shmid, (unsigned char*)0, 0)) == -1){ printf("server shmat failed.\n"); exit(1); } for(i=0;;i++){ printf("Enter text:"); fgets(readbuf, SHMSZ, stdin); semaphore_P(producer); printf("process %d enter pv key area", getpid()); sprintf(shm, "Message %4d from producer %d is \"%s\"\n",i, getpid(), readbuf); semaphore_V(consumer); if(strcmp(readbuf, "end") == 0){ break; } } return 0; }
3、消费者程序ConsumerProcess.c:
#include "myshm.h" int main(){ char * shm; int shmid; int producer, consumer, i; if((consumer = semget((key_t)1234, 1, IPC_CREAT|0660)) == -1){ printf("consumer semget failed.\n"); exit(1); } //init_a_semaphore(consumer, 0, 1); if((producer = semget((key_t)5678, 1, IPC_CREAT|0660)) == -1){ printf("producer semget failed.\n"); exit(1); } //init_a_semaphore(producer, 0, 1); if((shmid = shmget(ftok("shared", 0), SHMSZ, 0666|IPC_CREAT)) == -1){ printf("shmget failed\n"); exit(1); } if((shm = shmat(shmid, (unsigned char *)0, 0)) == -1){ printf("shmat failed.\n"); exit(1); } for(i=0;;i++){ printf("Prepare to get Data from memory\n"); semaphore_P(consumer); printf("enter pv key memory\n"); printf("Data received:%s\n", shm); sleep(1); semaphore_V(producer); if(strcmp(shm, "end") == 0){ break; } } semctl(producer, 0, IPC_RMID,0); semctl(consumer, 0, IPC_RMID, 0); return 1; }