/*
名称:有名信号量实现消费者生产者问题
说明:本实验实现的是进程同步中经典的消费者生产者的问题。在本实验中解决的是生产者消费者在多个缓冲区中涉及的同步和互斥问题。
对于一个缓冲区还是多个缓冲区的问题,其主要区别在于解决方案中是不是该包括互斥部分。
对于一个缓冲区,不需要包括互斥部分,因为只有一个缓冲区,生产者和消费者同步连续运行,不会涉及到竞争缓冲区的问题。(或者说,竞争缓冲区的问题已经在解决生产者和消费者同步的过程中解决了。)而对于多个缓冲区,就涉及到互斥部分,这解决的是N个消费者之间的对缓冲区的互斥访问(当然还有N个生产者之间的),这就是说,本实验可以同时运行多个生产者程序和多个消费者程序。(当然,一个缓冲区的问题也可以运行多个生产者和多个消费者,不过没什么影响,因为只有一个缓冲区,也即信号量最大就是1)。
需要说明的是,本实验的缓冲区是通过共享了int类型的数组实现的,每次生产或者消费的单位是一个int单元。另外,本实验共享了相同程序之间共享了读、写指针。
由于本人的刚学同步和互斥这一部分,所以程序写的不是很好。linux下运行程序时,会有上次的信号量值保存在共享内存空间中(这也可能说明了,共享的信号量在程序结束后,不会被立即清除)。为了清除这个共享信号量,本人采取了最极端的做法–重启linux。
*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
//创建模式权限
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(int argc,char **argv)
{
sem_t *info_full; /* 信号量info_full用于缓冲区满*/
sem_t *info_empty; /*信号量info_empty用于缓冲区空*/
sem_t *lock; //用于相同进程间的互斥访问
int i;
const int SIZE = 4096; //共享缓冲区的个数
const int size = 1; //共享1个写指针
int *wr_count; //共享写指针
int shm_fd;
int *ptr; //共享缓冲区的首地址
int value;
pid_t pid = getpid();
//创建info_full信号量,初始值为0,缓冲区为空
if((info_full = sem_open("full",O_CREAT,FILE_MODE,0)) == SEM_FAILED)
{
printf("sem_open %s Error\n",argv[0]);
exit(-1);
}
//创建info_empty信号量,初始值为4096,缓冲区为空
if((info_empty = sem_open("empty",O_CREAT,FILE_MODE,SIZE)) == SEM_FAILED)
{
printf("sem_open %s Error\n",argv[0]);
exit(-1);
}
//创建lock信号量,初始值为1,表示一开始未上锁
if((lock = sem_open("lock",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
{
printf("sem_open %s Error\n",argv[0]);
exit(-1);
}
sem_getvalue(info_empty,&value);
printf("info_empty value is %d.\n",value);
sem_getvalue(info_full,&value);
printf("info_full value is %d.\n",value);
sem_getvalue(lock,&value);
printf("lock value is %d.\n",value);
//创建共享内存空间
/* create the shared memory segment */
shm_fd = shm_open("buf", O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment */
ftruncate(shm_fd,SIZE);
/* now map the shared memory segment in the address space of the process */
ptr =(int*) mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
printf("Map buf failed\n");
return -1;
}
//创建共享写指针内存空间
/* create the shared memory segment */
shm_fd = shm_open("wr_count", O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment */
ftruncate(shm_fd,size);
/* now map the shared memory segment in the address space of the process */
wr_count = (int *)mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (wr_count == MAP_FAILED) {
printf("Map count failed\n");
return -1;
}
printf("producer--wr_count:%d\n",*wr_count);
//*wr_count = 0; //指向第*p_count个缓冲区
i = 0;
while(1)
{
sem_wait(info_empty); //等待缓冲区空
sem_wait(lock);
ptr[*wr_count] = i++;
*wr_count = *wr_count+1;
printf("I am the producer %d ,I has produced the %d.\n",pid,i);
sem_post(lock);
sem_post(info_full); //宣布缓冲区已空
sleep(3);
}
sem_close(info_empty);
sem_close(info_full);
//sem_unlink(SEM_INFO);
return 0;
}