问题
In my application I need to share memory
between parent and child (using fork
+execl
).
I use memfd_create
to allocate memory, because it provides a
file descriptor, which may be conveniently used in child
process (the discriptor is tied to stdin via dup2
before execl
)
to attach to the allocated memory.
I do not use write
and read
- I use pointers
to read and write memory directly.
The only piece of the puzzle which is left to solve
is how to get the address of memory, allocated
via fd = memfd_create ...
.
Using mmap
is undesirable, because it duplicates the memory, instead of giving the
memory address already allocated by memfd_create
.
This is demonstrated by the following code.
In its output each mmap
address is incremented by 4096
, which is the size of memory, referred to by fd
:
0x7f98411c1000
0x7f98411c0000
whereas if mmap
had given the direct address,
addresses in the output would be the same.
#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;
}
So, how to get direct address, avoiding memory duplication
by mmap
?
回答1:
Not sure if you still need an answer, since you have written the main point in your own answer, but just adding this to be sure it is complete:
memfd_create creates a memory-only file (meaning it is not stored on disk, although it can be swapped out). As you write in your answer, it returns a file descriptor.
mmap ensures that the file behind a file descriptor is in memory (which requires no action in case of a memory-only file), and gives you a pointer to that memory. It does not copy the memory (except from disk to memory when mapping a file from disk). If the same file is mapped multiple times, each call to mmap reserves a new region of virtual memory, but all those regions access the same portion of physical memory.
So the short answer to your question is that you misunderstand mmap; it does not copy the memory, and it is the perfect solution to your problem.
回答2:
Instead of physical address we get a file descriptor from memfd_create
.
File descriptor is a handle through which we get access to the memory
(i.e., it is a mapping from file discriptor to memory). A file
descriptor is more convenient to work with, than memory address:
it can be passed to forked processes, etc (see OP).
mmap
just maps physical address (referred to by file descriptor)
to a virtual address. A virtual memory address is in fact the memory
address, because user never sees physical addresses.
Each mmap call returns a different virtual address, all of which
are mapped to the same physical address by the kernel.
来源:https://stackoverflow.com/questions/49567475/how-to-get-memory-address-from-memfd-create