如何从memfd_create获取内存地址?

How to get memory address from memfd_create?

在我的应用程序中我需要共享内存 父子之间(使用 fork+execl)。 我使用 memfd_create 来分配内存,因为它提供了 文件描述符,可以方便地在子进程中使用 过程(描述符在 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?

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

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

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

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

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

所以对你的问题的简短回答是你误解了mmap;不拷贝内存,完美解决你的问题