c中的消费者生产者问题

标签 c multithreading ipc producer-consumer

嘿,所以我正在做一个简单的生产者问题,但由于某种原因,我的生产者运行,然后我的消费者运行,即使我的生产者一旦无法将信号量初始化为 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);
        }else{buffer->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++;
        }else{finished = true;}

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

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

最佳答案

通过消费者调用

sem_post(&empty);

您确保生产者的步骤多于 15 个。

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

sizeof(int) >= sizeof(struct shared_mem)

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

关于c中的消费者生产者问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22559768/

相关文章:

c# - 将参数发送到驻留在另一个进程中的应用程序实例

python - 我怎么知道子进程何时死亡?

使用 --enable-ssl 编译失败,但如果未指定则可以工作

c++ - Eclipse CDT - 如何在外部控制台 (cmd.exe) 中运行已编译的 .exe

c - 在 C 语言中,为什么只在初始化已创建线程列表后才调用 pthread_join?

c# - 使用任务计划程序的应用程序很快就会耗尽内存

C11 相当于 POSIX flockfile()?

c++ - linux 防止文件描述符在程序退出时关闭

java - 创建一个支持 "snapshots"的 ConcurrentHashMap

electron - 在ipcRenderer Electron 之外使用arg?