消费者生产者问题c

时间:2014-03-21 13:11:35

标签: 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个字母放入缓冲区后,生产者不会被阻止。

2 个答案:

答案 0 :(得分:0)

消费者致电

sem_post(&empty);

你要确保生产者的步骤多于15步。

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

sizeof(int) >= sizeof(struct shared_mem)

这可能是正确的,直到你没有向结构添加字段

答案 1 :(得分:0)

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

我需要在学校计算机上使用该命令:

gcc -o ass3 ass3.c -lpthread -lrt

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