问题
I need to find a way to use mmap instead of malloc. How is this possible? (I am not using libc only syscalls) And yes brk() is possible. I used sbrk() but realized its not sys-call... (x86 inline assembly)
I've been looking around and saw this: How to use mmap to allocate a memory in heap? But it didn't help for me, because I had a segfault.
Basically, all I want to do a create 3 slabs of memory for storing characters.
Say,
char * x = malloc(1000);
char * y = malloc(2000);
char * z = malloc(3000);
How is this possible with mmap and how to free it later with munmap?
回答1:
Did you carefully read the mmap(2) man page? I recommend reading it several times.
Notice that you can only ask the kernel [thru mmap
etc...] to manage memory aligned to and multiple of the page size sysconf(_SC_PAGE_SIZE)
which is often 4096 bytes (and I am supposing that in my answer).
Then you might do:
size_t page_size = sysconf(_SC_PAGE_SIZE);
assert (page_size == 4096); // otherwise this code is wrong
// 1000 bytes fit into 1*4096
char *x = mmap (NULL, page_size, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS, -1, (off_t)0);
if (x == MMAP_FAILED) perror("mmap x"), exit (EXIT_FAILURE);
// 2000 bytes fit into 1*4096
char *y = mmap (NULL, page_size, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS, -1, (off_t)0);
if (y == MMAP_FAILED) perror("mmap y"), exit (EXIT_FAILURE);
later to free the memory, use
if (munmap(x, page_size))
perror("munmap x"), exit(EXIT_FAILURE);
etc
If you want to allocate 5Kbytes, you'll need two pages (because 5Kbytes < 2*4096 and 5Kbytes > 1*4096) i.e. mmap(NULL, 2*page_size,
...
Actually, all of your x
, y
, z
takes only 8000 bytes and could fit into two, not three, pages... But then you could only munmap
that memory together.
Be aware that mmap
is a system call which might be quite expensive. malloc
implementations take care to avoid calling it too often, that is why they manage previously free
-d zones to reuse them later (in further malloc
-s) without any syscall. In practice, most malloc
implementations manage differently big allocations (e.g. more than a megabyte), which are often mmap
-ed at malloc
and munmap
-ed at free
time.... You could study the source code of some malloc
. The one from MUSL Libc might be easier to read than the Glibc malloc
.
BTW, the file /proc/1234/maps
is showing you the memory map of process of pid 1234. Try also cat /proc/self/maps
in a terminal, it shows the memory map of that cat
process.
回答2:
You can call mmap
to make an anonymous mapping in x86 asm with something like:
mov eax, 192 ; mmap
xor ebx, ebx ; addr = NULL
mov ecx, 4096 ; len = 4096
mov edx, $7 ; prot = PROT_READ|PROT_WRITE|PROT_EXEC
mov esi, $22 ; flags = MAP_PRIVATE|MAP_ANONYMOUS
mov edi, -1 ; fd = -1 (Ignored for MAP_ANONYMOUS)
xor ebp, ebp ; offset = 0 (4096*0) (Ignored for MAP_ANONYMOUS)
int $80 ; make call (There are other ways to do this too)
来源:https://stackoverflow.com/questions/14786484/mmap-substitute-for-malloc