Почему этот код разделяемой памяти POSIX дает ошибку сегментации? - PullRequest
0 голосов
/ 10 ноября 2018
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/mman.h>

int main()
{
    const int SIZE = 500;
    const char *name = "name";
    int fd;
    char *ptr = NULL;
    pid_t pid;
    pid = fork();

    if (pid < 0) {
        fprintf(stderr, "Fork Failed");
        return 1;
    }
    else if (pid == 0) {
        fd = shm_open(name,O_CREAT | O_RDWR,0666);
        ftruncate(fd, SIZE);
        ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        sprintf(ptr, "%s", "Hello, World!\n");
        return 0;
    }
    else {
        wait(NULL);
        fd = shm_open(name, O_RDONLY, 0666);
        ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        printf("%s\n", (char *)ptr);
    }
    return 0;
}

В основном я хочу создать общую память в дочернем процессе и получить к ней доступ из родительского процесса.

В дочернем процессе mmap работает нормально. Когда я печатаю, используя указатель, возвращенный mmap, он на самом деле печатает Hello, World!, но тот же самый вывод выдает ошибку сегмента от родителя.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Сбой из-за этой выдержки из man :

O_RDONLY   Open the object for read access.  A shared memory object
           opened in this way can be mmap(2)ed only for read
           (PROT_READ) access.

Вы попытались:

fd = shm_open(name, O_RDONLY, 0666);
//                  ^^^^^^^^
ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
//                                    ^^^^^^^^^^^^ incorrect!

Еще одно замечание: ваш name должен следовать рекомендации man по переносимости:

For portable use, a shared memory object should be identified by a name
of the form /somename; that is, a null-terminated string of up to
NAME_MAX (i.e., 255) characters consisting of an initial slash,
followed by one or more characters, none of which are slashes.

Наконец, у вас есть несколько ненужных (char *) приведений и всегда проверка ошибок возвращаемых значений.

0 голосов
/ 10 ноября 2018

В родительском (pid! = 0) вы открыли объект O_RDONLY, но сопоставили его с PROT_WRITE, MAP_SHARED. Удалить | PROT_WRITE и ты в порядке. Возможно, вы захотите проверить возвращаемые значения на наличие ошибок нечетное время.

...