简体   繁体   中英

Shared Memory and semaphores: Unexpected segmantation fault

I'm trying to create 2 programs consisting of a producer and a consumer. The producer generates a set amount of random numbers from 0 to 9 and stores them in a circular_queue in shared memory and then the consumer reads the queue from shared memory and prints the frequency of each number from 0 to 9.

The producer is not giving me an error. However, when I try to run the consumer, the program immediately gives a segmentation fault. I was hoping someone could detect what is wrong. I also wanted to know if there is any way for me to check the dev/shm directory to verify that the shared memory file I'm trying to create is working? Thanks

PRODUCER

#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;
} 

CONSUMER

 #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;
 }

CIRCULAR QUEUE

#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));

The realloc function doesn't allocate shared memory. If you don't put the queue in shared memory, it isn't shared. When you try to access pointers into regular memory allocated in one process from another process, the most common result would be a crash.

You need to put all shared data in shared memory. When you share pointers across processes, you need to share a relative pointer into the shared memory and each process needs to convert that into a pointer valid in its address space by adding in its particular base address of the shared memory segment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM