使用信号量的生产者消费者-c

时间:2017-11-22 15:42:50

标签: c synchronization multiprocessing semaphore producer-consumer

问题:

  • 所有进程都有一系列元素。
  • Producer在其数组中存储一个值。
  • 所有使用者(n)必须在生产者可以生成其他元素之前将此值存储在其数组中。
  • 所有消费者都应该存储该元素并等待生产者创建一个新元素。

所以在我的实现中我使用三个信号量:all(作为屏障)= 1,new = 0和mutex = 1。我也使用共享计数器= 0来计算有多少消费者已经阅读了元素。

代码:

#include <time.h>
#include <sys/shm.h>
#include "stdio.h"
#include "sys/sem.h"
#include "stdlib.h"
#include "unistd.h"

int sem_id;
int shmid;
typedef struct sharedMemory{
    int value;
}sharedMemory;

union semun {
    int                 val;
    struct semid_ds *   buf;
    unsigned short *    array;
};

#define M 4
#define N 2

typedef enum semIndex{
    mutex= 0,
    all=1,
    new=2
}semIndex;


int sem_init(semIndex index,int val){
    union semun sem_union;
    sem_union.val = val;
    if (semctl(sem_id, index, SETVAL, sem_union) == -1) return 0;
    return 1;
}

int up(semIndex index) {
    struct sembuf sem_b;
    sem_b.sem_num = index;
    sem_b.sem_op = 1;
    if (semop(sem_id, &sem_b, 1) == -1) {
        perror("Failed to up");
        return 0;
    }
    return 1;
}

int down(semIndex index) {
    struct sembuf sem_b;
    sem_b.sem_num = index;
    sem_b.sem_op = -1;
    if (semop(sem_id, &sem_b, 1) == -1) {
        perror("Failed to up");
        return 0;
    }
    return 1;
}

void *getShMemory(int memory) {
    shmid = shmget((key_t)1234+memory, sizeof(sharedMemory), 0666 | IPC_CREAT);
    if (shmid == -1) {
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }
    void* shared_memory = shmat(shmid, (void *)0, 0);
    if (shared_memory == (void *)-1) {
        fprintf(stderr, "shmat failed\n");
        exit(EXIT_FAILURE);
    }
    return shared_memory;
}

int main(void){
    srand(getpid() + rand()%500);
    int *array = malloc(M * sizeof(int));
    for (int i = 0; i < M; ++i) {
        array[i] = rand() % 20;
    }
    sem_id = semget(6846, 3, 0666 | IPC_CREAT);
    sharedMemory *sharedMem = (sharedMemory*) getShMemory(2);
    sem_init(all,1);
    sem_init(mutex,1);
    sem_init(new,0);
    pid_t pid = fork();
    if (pid>0){
        for (int i = 0; i < M; ++i) {
            down(all);
            down(mutex);
            sharedMem->value = array[i];
            up(mutex);
            up(new);
        }
        for (int j = 0; j < M; ++j) {
            printf("%d,",array[j]);
        }
        putchar('\n');
    }
    else{
        sem_id = semget(6846, 3, 0666 | IPC_CREAT);
        int *array = malloc(M*sizeof(int));
        sharedMemory* consumerMem = (sharedMemory*)getShMemory(1);
        down(new);
        consumerMem->value = 0;

        for(int i=0;i<N;++i){
                if(fork() == 0) {
                    for (int j = 0; j < M; ++j) {
                        down(mutex);
                        consumerMem = (sharedMemory*)getShMemory(1);
                        sharedMemory *sharedMem = (sharedMemory*) getShMemory(2);
                        array[j] = sharedMem->value;
                        consumerMem->value++;
                        up(mutex);

                        if (consumerMem->value == N) {
                            down(mutex);
                            consumerMem->value = 0;
                            up(mutex);
                            up(all);            //signal producer to create new element
                        }
                        down(new);   //wait for new element
                        up(new);     //unblock one more consumer
                    }
                    for (int j = 0; j < M; ++j) {
                        printf("%d,",array[j]);
                    }
                    putchar('\n');
                    exit(0);
                }
            }
        }
}

有时它按预期工作,所以它应该是竞争条件,但我无法指出它。任何线索?

更新的 我设法与Clion一起运行调试。我无法用调试器复制问题,因此更难确定问题。

0 个答案:

没有答案