c中的消费者生产者问题

Posted

技术标签:

【中文标题】c中的消费者生产者问题【英文标题】:Consumer Producer issue in c 【发布时间】:2014-03-21 13:11:35 【问题描述】:

嘿,所以我正在做一个简单的生产者问题,但由于某种原因,我的生产者运行通过,然后我的消费者运行,即使我的生产者一旦无法将信号量初始化为 15 就应该停止:

#define _REENTRANT
#define BUFFER_SIZE 15
#define SHMKEY ((key_t) 7890)
//The buffer should be treated as circular buffer
#define BUFFER_WRAP(x) x%BUFFER_SIZE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>
#include <stdbool.h>

//headers
void* producerFunc(void *);
void* consumerFunc(void *);

//Structures
typedef struct

    char* value;
 shared_mem;  

typedef struct

    int value;
 shared_dat;

//You will require 3 semaphores;
sem_t empty;
sem_t full;
sem_t crit_sec;
int start = 0;
int end = 0;
shared_mem *buffer;
//while(fscanf(fp,"%c",&newChar) != EOF)
char newChar;
FILE* fp;


shared_dat *counter;




//To compile program use the command:
//gcc name_of_program.c -lpthread -lrt



int main(void)

    fp = fopen("mytest.dat", "r");

    /******************init everything: threads, sems, shmem**********/
    int r=0;
    int i;
    int shmid;    /* shared memory ID */
    pthread_t producer[1];     /* process id for thread 1 */
    pthread_t consumer[1];     /* process id for thread 2 */
    pthread_attr_t attr;     /* attribute pointer array */



    int status;
    char *shmadd;
    shmadd = (char *) 0;
    int value, value1;

    //create shared memory seg, if return -1 then print error
    if ((shmid = shmget (SHMKEY, sizeof(int), IPC_CREAT | 0666)) < 0)
      perror ("shmget");
      exit (1);
    

    //connect process to shared memory segment.  If return is -1 then print error
    if ((buffer = (shared_mem *) shmat (shmid, shmadd, 0)) == (shared_mem *) -1)
      perror ("shmat");
      exit (0);
    

    //set the 
    char buffer_array[15];
    buffer->value = buffer_array;

    counter = (shared_dat *) malloc(sizeof(shared_dat));

    /* initialize shared memory to 0 */
    counter->value = 0 ;

    sem_init(&empty,0,BUFFER_SIZE);
    sem_init(&full,0,0);
    sem_init(&crit_sec,0,1);

    printf("1 - I am here %d in pid %d\n",r,getpid());

    fflush(stdout);
    /* Required to schedule thread independently.
    Otherwise use NULL in place of attr. */
    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);  /* system-wide contention */ 

    /* end to schedule thread independently */

    /* Create the threads */
    pthread_create(&producer[0], &attr, producerFunc, NULL);
    pthread_create(&consumer[0], &attr, consumerFunc, NULL);

    /* Wait for the threads to finish */
    pthread_join(producer[0], NULL);
    pthread_join(consumer[0], NULL);


    /***************once threads finished and * reached in buffer************/
    printf("from parent counter  =  %d\n", counter->value);
    printf("---------------------------------------------------------------------------\n");
    printf("\t\t    End of simulation\n");

    sem_destroy(&empty);
    sem_destroy(&full);
    sem_destroy(&crit_sec);

    //release shared mem with IPC_RMID and print "end"
    if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1)
      perror ("shmctl");
      exit (-1);
    

    fclose(fp);
    exit(0);    







void* producerFunc(void *arg)
    bool finished = false;
    while(!finished)
        sem_wait(&empty);
        sem_wait(&crit_sec);
        end++;

        if(fscanf(fp,"%c",&newChar) != EOF)
            buffer->value[BUFFER_WRAP(end)] = newChar;
            printf("%c",newChar);
        elsebuffer->value[BUFFER_WRAP(end)] = '*';
            finished = true;
        

        sem_post(&crit_sec);
        sem_post(&full);
    


void* consumerFunc(void *arg)
    bool finished = false;
    char val;
    while(!finished)
        sem_wait(&full);
        sem_wait(&crit_sec);
        start++;

        //sleep for 1 sec
        sleep(1);
        if((val = buffer->value[BUFFER_WRAP(start)]) != '*')
            printf("Consuming: %c\n",val);
            counter->value++;
        elsefinished = true;

        sem_post(&crit_sec);
        sem_post(&empty);
    

由于某种原因,在将 15 个字母放入缓冲区后,生产者并未被阻塞。

【问题讨论】:

【参考方案1】:

消费者调用

sem_post(&empty);

您要确保生产者的步骤超过 15 个。

另请注意,在您的 shmget() 调用中,您假设

sizeof(int) >= sizeof(struct shared_mem)

这可能是正确的,直到您不向结构中添加字段

【讨论】:

有谁知道为什么 -lrt 选项在 mac 上不起作用?这就是让我的代码在 Windows 计算机上运行的原因。【参考方案2】:

所以我无法准确解释我的解决方案,但我在学校运行 Windows 7 的机器上编译了代码。我使用的是 mac。我知道问题出在我用来编译的选项上。

我需要在学校电脑上使用命令:

gcc -o ass3 ass3.c -lpthread -lrt

这使信号量起作用。同样的命令在我的 mac 上不起作用。显然 -lrt 选项在 mac 上不起作用。有谁知道为什么或等价物是什么,所以我可以让它在我的家用电脑上工作?

【讨论】:

以上是关于c中的消费者生产者问题的主要内容,如果未能解决你的问题,请参考以下文章

请问如何用C语言实现“生产者与消费者问题”?(最好附上完整的C语言源代码)

C/C++实现生产者消费者模式

生产者-消费者”问题 用C语言编写

用C语言实现--生产者与消费者的问题(PV操作)

综合运用: C++11 多线程下生产者消费者模型详解(转)

C++11实现生产者消费者问题