如何从memfd_create获取内存地址?

时间:2018-03-30 02:03:13

标签: shared-memory mmap

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

我不使用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

2 个答案:

答案 0 :(得分:1)

由于您已经在自己的答案中写下了要点,因此不确定是否仍然需要答案,只是添加此内容以确保它是完整的:

memfd_create创建一个仅内存的文件(意味着它可以存储在磁盘上,尽管可以交换出来)。在您写答案时,它会返回文件描述符。

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

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

答案 1 :(得分:0)

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

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