共享内存和信号量:意外的分段错误

Shared Memory and semaphores: Unexpected segmantation fault

我正在尝试创建由生产者和消费者组成的 2 个程序。生产者生成一组从 0 到 9 的随机数,并将它们存储在共享内存中的 circular_queue 中,然后消费者从共享内存中读取队列并打印每个数字从 0 到 9 的频率。

生产者没有给我错误。但是,当我尝试 运行 消费者时,程序立即给出了分段错误。我希望有人能检测出问题所在。我还想知道是否有任何方法可以检查 dev/shm 目录以验证我尝试创建的共享内存文件是否正常工作?谢谢

制作人

#include <fcntl.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include "cola_circular.c"

#define SHM_NAME "/shm_eje4"
#define QUEUE_SIZE 10

typedef struct {
    circular_queue queue;
    sem_t sem_mutex;
} ShmStruct;

int main(int argc, char *argv[]) {
    int fd_shm;
    int i;
    pid_t ppid = 0;
    pid_t pid = 0;
    ShmStruct *input;

    if (argc < 3) {
        fprintf(stderr,"usage: %s <n_numbers> <generation_method>", argv[0]);
        return EXIT_FAILURE;
    } else {
        if (atoi(argv[1]) < 0) {
            fprintf(stderr,"<n_numbers> has to be greater than or equal to 0");
            return EXIT_FAILURE;
        }
        if (atoi(argv[2]) < 0 || atoi(argv[2]) > 1) {
            fprintf(stderr,"<generation_method>: 0 for random, 1 for sequential");
            return EXIT_FAILURE;
        }
    }

    /* Crear memoria compartida para la cola, semafaros */
    fd_shm = shm_open(SHM_NAME,
         O_RDWR | O_CREAT | O_EXCL,
          S_IRUSR | S_IWUSR);
    if  (fd_shm == -1) {
        fprintf(stderr, "Error creating the shared memory segments");
        shm_unlink(SHM_NAME);
        return EXIT_FAILURE;
    }

    /* Cambiar el tamaño del segmento de memoria */
    if (ftruncate(fd_shm, sizeof(ShmStruct)) == -1) {
        fprintf(stderr, "Error resizing the shared memory segment\n");
        shm_unlink(SHM_NAME);
        close(fd_shm);
        return EXIT_FAILURE;
    }

    /* Mapear el segmento de memoria */
    input = mmap(NULL,
         sizeof(*input),
         PROT_READ | PROT_WRITE, MAP_SHARED,
         fd_shm,
         0);
    close(fd_shm);
    if (input == MAP_FAILED) {
        fprintf(stderr, "Error mapping the shared memory segment\n");
        shm_unlink(SHM_NAME);
        close(fd_shm);
        return EXIT_FAILURE;
    }

    if (sem_init(&(input->sem_mutex),1,1) < 0) {
        fprintf(stderr, "Error initializing mutex semaphore\n");
        perror("sem_init");
        return EXIT_FAILURE;
    }
    input->queue = queue_ini(QUEUE_SIZE);

    /*Generamos N numeros aleatorios/secuencia entre 0 y 9*/
    sem_wait(&(input->sem_mutex));
    if (argv[2] == 0) {
        for (i=0; i<atoi(argv[1]); i++) {
            insert_queue(input->queue, rand()%10);
        }
    } else if (atoi(argv[2]) == 1) {
        for (i=0; i<atoi(argv[1]); i++) {
            insert_queue(input->queue, i%10);
        }
    }
    sem_post(&(input->sem_mutex));

    /*El programa espera un caracter mientras ejecutamos el hijo*/
    getchar();

    sem_destroy(&(input->sem_mutex));
    munmap(input, sizeof(*input));
    shm_unlink(SHM_NAME);
    close(fd_shm);
    return EXIT_SUCCESS;
} 

消费者

 #include <errno.h>
 #include <fcntl.h>
 #include <math.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <semaphore.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
 #include "cola_circular.c"

 #define SHM_NAME "/shm_eje4"

 typedef struct {
     circular_queue queue;
     sem_t sem_mutex;
 } ShmStruct;

 int  main(void) {
     fprintf(stdout, "1");
     int i;
     int count[10];
     int fd_shm = shm_open(SHM_NAME,
        O_RDONLY,
        0);
    if (fd_shm == -1) {
        fprintf(stderr, "Error opening the shared memory segment\n");
        return EXIT_FAILURE;
    }

    ShmStruct *output = mmap(NULL,
        sizeof(*output),
        PROT_READ,
        MAP_SHARED,
        fd_shm,
        0);
    close(fd_shm);
    if (output == MAP_FAILED) {
        fprintf(stderr, "Error mapping the shared memory segment\n");
        return EXIT_FAILURE;
    }

    sem_wait(&(output->sem_mutex));
    for (i=0; i<10; i++) {
        count[i] = 0;
    }
    for (i=0; i<output->queue.num; i++) {
        count[output->queue.queue[i]]++;
    }
    fprintf(stdout, "Histograma de numeros de queue:\n");
    for  (i=0; i<10; i++) {
        fprintf(stdout, "%d ---> %d\n", i, count[i]);
    }
    sem_post(&(output->sem_mutex));

    munmap(output, sizeof(*output));
    close(fd_shm);
    return EXIT_SUCCESS;
 }

循环队列

#include <stdio.h>
#include <stdlib.h>

#define SIZE 124

typedef struct circular_queue {
    int *queue;
    int rear;
    int front;
    int size;
    int num;
} circular_queue;

circular_queue queue_ini(int size) {
    int i;
    circular_queue ret;
    ret.queue = (int*) malloc(0);
    ret.rear = -1;
    ret.front = -1;
    ret.size = size;
    ret.num = 0;
    return ret;
}

int queue_isFull(circular_queue queue) {
    if (queue.num == queue.size) {
        return 1;
    } else {
        fprintf(stderr, "Error inseting, the queue is full.\n");
        return 0;
    }
}

int insert_queue(circular_queue queue, int num) {
    if (queue_isFull(queue) == 1) {
        return 0;
    }
    ret.queue = (int*) realloc(ret.queue, sizeof(int)*(ret.num+1));
    if (queue.front == -1) queue.front = 0;
    queue.rear = (queue.rear+1)%SIZE;
    queue.queue[queue.rear] = num;
    queue.num++;
    fprintf(stdout, "\n Inserted --> %d", queue.num);
    return 1;
}

int queue_isEmpty(circular_queue queue) {
    if  (queue.num == 0) return 1;
    return 0;
}
ret.queue = (int*) realloc(sizeof(int)*(ret.num+1));

realloc 函数不分配共享内存。如果你不把队列放在共享内存中,它就不会被共享。当您尝试从另一个进程访问指向一个进程中分配的常规内存的指针时,最常见的结果是崩溃。

您需要将所有共享数据放在共享内存中。当您跨进程共享指针时,您需要将一个相对指针共享到共享内存中,并且每个进程都需要通过添加其共享内存段的特定基地址来将其转换为在其地址 space 中有效的指针。