【问题标题】:How to get memory address from memfd_create?如何从 memfd_create 获取内存地址?
【发布时间】:2018-09-09 02:02:10
【问题描述】:

在我的应用程序中,我需要共享内存 父母和孩子之间(使用fork+execl)。 我使用memfd_create 来分配内存,因为它提供了一个 文件描述符,可以方便地在child中使用 进程(在execl 之前,描述符通过dup2 绑定到标准输入) 附加到分配的内存。

我不使用 writeread - 我使用指针 直接读写内存。

唯一需要解决的难题 是如何获取内存的地址,分配 通过fd = memfd_create ...

使用mmap 是不可取的,因为它复制了内存,而不是提供 memfd_create已经分配了内存地址。

以下代码证明了这一点。 在其输出中,每个mmap 地址都增加了4096,这是内存的大小,由fd 引用:

0x7f98411c1000
0x7f98411c0000

而如果mmap 给出了直接地址, 输出中的地址将是相同的。

#include <stdio.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
int main(void)
{
    int fd = syscall(SYS_memfd_create, "shm", 0);
    if (fd == -1) return 1;

    size_t size = 4096; /* minimal */

    int check = ftruncate(fd, size);
    if (check == -1) return 1;

    void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (ptr == MAP_FAILED) return 1;

    void *ptr2 = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (ptr2 == MAP_FAILED) return 1;

    printf("%p\n%p\n", ptr, ptr2);

    return 0;
}

那么,如何获取直接地址,避免内存重复 mmap?

【问题讨论】:

    标签: shared-memory mmap


    【解决方案1】:

    不确定您是否还需要答案,因为您已经在自己的答案中写下了要点,但只需添加它以确保它是完整的:

    memfd_create 创建一个仅限内存的文件(这意味着它不存储在磁盘上,尽管它可以被换出)。正如您在答案中所写,它会返回一个文件描述符。

    mmap 确保文件描述符后面的文件在内存中(在仅内存文件的情况下不需要任何操作),并为您提供指向该内存的指针。它不复制内存(从磁盘映射文件时从磁盘到内存除外)。如果同一个文件被多次映射,每次调用 mmap 都会保留一个新的虚拟内存区域,但所有这些区域都访问物理内存的同一部分。

    所以对您的问题的简短回答是您误解了 mmap;它不会复制内存,它是您问题的完美解决方案。

    【讨论】:

      【解决方案2】:

      我们从memfd_create 获取文件描述符,而不是物理地址。 文件描述符是一个句柄,通过它我们可以访问内存 (即,它是从文件描述符到内存的映射)。一份文件 描述符比内存地址更方便使用: 它可以传递给分叉进程等(参见 OP)。

      mmap 只是映射物理地址(由文件描述符引用) 到一个虚拟地址。虚拟内存地址实际上是 内存 地址,因为用户永远不会看到物理地址。 每个 mmap 调用返回一个不同的虚拟地址,所有这些 被内核映射到同一个物理地址。

      【讨论】:

        猜你喜欢
        • 2012-07-05
        • 1970-01-01
        • 1970-01-01
        • 2017-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多