【问题标题】:Can't access shared memory created in child process [duplicate]无法访问在子进程中创建的共享内存 [重复]
【发布时间】:2015-11-30 23:51:20
【问题描述】:

我想从一个子进程创建可以从其他进程使用的共享内存。但是,当我在子级中创建共享内存时,父级在尝试使用共享内存中的指针时会崩溃。

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

struct list_node
{
    char *data;
};

static int create_shared(void **pointer, int size)
{
    *pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if(*pointer == MAP_FAILED)
    {
        perror("mmap:");
        return -1;
    }

    return 0;
}

int main(void)
{
    int rtrn;
    pid_t pid;
    struct list_node *node;

    pid = fork();
    if(pid == 0)
    {
        rtrn = create_shared((void **)&node, sizeof(struct list_node));
        if(rtrn < 0)
        {
            printf("Can't create shared node\n");
            return -1;
        }

        rtrn = asprintf(&node->data, "Test\n");
        if(rtrn < 0)
        {
            perror("asprintf:");
            return -1;
        }

        printf("data_child: %s\n", node->data);
    }
    else if(pid > 0)
    {
        /* Parent. */

        sleep(1); // Make sure child runs first.

        printf("data_parent: %s\n", node->data);
    }
    else
    {
        perror("fork");
        return -1;
    }

    return 0;
}

但是当我在父进程中创建共享内存时,它可以从子进程中使用,它不仅仅是来自fork() 的副本,因为子进程可以更改指针,父进程可以看到它。在下面的示例中,孩子将 node-&gt;data 的值从 test 更改为 best。

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

struct list_node
{
    char *data;
};

static int create_shared(void **pointer, int size)
{
    *pointer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if(*pointer == MAP_FAILED)
    {
        perror("mmap:");
        return -1;
    }

    return 0;
}

int main(void)
{
    int rtrn;
    struct list_node *node;

    rtrn = create_shared((void **)&node, sizeof(struct list_node));
    if(rtrn < 0)
    {
        printf("Can't create shared node\n");
        return -1;
    }

    rtrn = asprintf(&node->data, "Test\n");
    if(rtrn < 0)
    {
        perror("asprintf:");
        return -1;
    }

    pid_t pid;

    pid = fork();
    if(pid == 0)
    {
        printf("data_child: %s\n", node->data);

        node->data = "Best";
    }
    else if(pid > 0)
    {
        /* Parent. */

        sleep(1); // Make sure child runs first.

        printf("data_parent: %s\n", node->data);
    }
    else
    {
        perror("fork");
        return -1;
    }

    return 0;
}

那么如何从子进程创建共享内存,以便父进程或其他子进程可以访问它?

编辑

我尝试使用 create_shared() aka mmap 将char *data 指向的内存标记为共享内存,但在尝试打印char *data 指向的字符串时仍然出现段错误。下面是我尝试将data 设置为共享内存的方法。我还尝试过 memcpy,认为仅将 char *data 设置为 test 只是将指针设置为非共享内存,但这也不起作用。

 rtrn = create_shared((void **)&node->data, 5);
 if(rtrn < 0)
 {
     printf("Can't create shared data\n");
     return -1;
 }

 node->data = "Test";
 //memcpy(node->data, "Test", 4); 

【问题讨论】:

  • @Dmitri 我认为您对副本的看法是正确的,感谢您指出那篇文章。
  • 此外,node-&gt;data 指向的字符串必须在该(或另一个)共享内存区域内,否则父级将无权访问它(即使它可以访问 node 本身)。

标签: c shared-memory


【解决方案1】:
char *data;

您共享了部分内存,但只包含一个指针。

它指向的位置对其他进程不可见。

共享字符串。或者,如果您知道它的最大长度,请使用字符数组而不是指针。


在您的第二个示例中,"Best" 是一个字符串文字,将被放置在可执行文件中。您设置了指向此地址的指针,并且由于两个进程使用相同的可执行文件,因此地址也将相同,并且指针将有效。

注意:我认为这超出了 C 标准的范围,我不确定 POSIX 标准对此有何规定,因此它可能不可移植......

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2016-10-19
    相关资源
    最近更新 更多