有名信号量实现消费者生产者问题

/*
名称:有名信号量实现消费者生产者问题
说明:本实验实现的是进程同步中经典的消费者生产者的问题。在本实验中解决的是生产者消费者在多个缓冲区中涉及的同步和互斥问题。
对于一个缓冲区还是多个缓冲区的问题,其主要区别在于解决方案中是不是该包括互斥部分。
对于一个缓冲区,不需要包括互斥部分,因为只有一个缓冲区,生产者和消费者同步连续运行,不会涉及到竞争缓冲区的问题。(或者说,竞争缓冲区的问题已经在解决生产者和消费者同步的过程中解决了。)而对于多个缓冲区,就涉及到互斥部分,这解决的是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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者-消费者问题是指一个共享的缓冲区间,生产者将对象放入该缓冲区间,消费者则将对象从缓冲区间取出。但是生产者消费者不能同时对缓冲区间进行操作,也就是说缓冲区间需要实现互斥访问。而信号可以用来控制对缓冲区间的访问,实现互斥。 具体地,在实现过程中需要定义两个信号,一个表示缓冲区间已有的对象数目,另一个表示缓冲区间空的对象数目。生产者在向缓冲区放置对象时,需要先使用空对象信号进行等待,直到缓冲区间还存在空对象,然后使用已有对象信号进行加锁,放入对象,释放已有对象信号消费者在从缓冲区取出对象时,需要先使用已有对象信号进行等待,直到缓冲区间有可用的对象,然后使用空对象信号进行加锁,取出对象,释放空对象信号。 下面给出一个简单的代码实现: ``` #include <pthread.h> #include <semaphore.h> #define MAX_ITEM 10 #define BUFFER_SIZE (MAX_ITEM + 1) int buffer[BUFFER_SIZE]; int in, out; sem_t empty, full, mutex; void *producer(void *arg) { int item; while (1) { /* produce an item */ item = ... /* wait for an empty slot */ sem_wait(&empty); /* lock the buffer */ sem_wait(&mutex); /* insert the item into the buffer */ buffer[in] = item; in = (in + 1) % BUFFER_SIZE; /* unlock the buffer */ sem_post(&mutex); /* signal a full slot */ sem_post(&full); } } void *consumer(void *arg) { int item; while (1) { /* wait for a full slot */ sem_wait(&full); /* lock the buffer */ sem_wait(&mutex); /* remove an item from the buffer */ item = buffer[out]; out = (out + 1) % BUFFER_SIZE; /* unlock the buffer */ sem_post(&mutex); /* signal an empty slot */ sem_post(&empty); /* consume the item */ ... } } int main() { pthread_t tid1, tid2; /* initialize the buffer */ in = out = 0; /* initialize the semaphores */ sem_init(&empty, 0, BUFFER_SIZE - 1); sem_init(&full, 0, 0); sem_init(&mutex, 0, 1); /* create the producer and consumer threads */ pthread_create(&tid1, NULL, producer, NULL); pthread_create(&tid2, NULL, consumer, NULL); /* wait for the threads to finish */ pthread_join(tid1, NULL); pthread_join(tid2, NULL); /* destroy the semaphores */ sem_destroy(&empty); sem_destroy(&full); sem_destroy(&mutex); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值