Using mmap(2) with a hint address
Ganael LAPLANCHE
ganael.laplanche at martymac.org
Tue Dec 20 08:25:45 UTC 2011
Hi folks,
I am trying to use mmap(2) with a hint address. Unfortunately, this address
seems to be ignored and I never manage to get the desired one, while it
seems to be free.
Here is my code (the same code on NetBSD and GNU/Linux returns the hint
address) :
8< ----------- >8
#include <stdio.h>
#include <string.h>
#include <errno.h>
/* mmap */
#include <sys/mman.h>
/* getpagesize */
#include <unistd.h>
/* round_page */
#include <machine/param.h>
int main(void)
{
size_t map_size = getpagesize();
/* first call, ask for one page, with hint */
char *map_hint = (char*)round_page(512*1024*1024);
printf("=> calling mmap with hint = %p, size = %zu\n", map_hint,
map_size);
void *addr = mmap(map_hint, map_size, PROT_READ | PROT_WRITE |
PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (addr == MAP_FAILED) {
printf("mmap failed: %s\n", strerror(errno));
}
else {
printf("mmap succeeded: addr = %p\n", addr);
#ifdef SLEEP
/* leave time to use 'procstat -v' */
sleep(10);
#endif
if(munmap(addr, map_size) != 0) {
printf("munmap failed: %s\n", strerror(errno));
}
}
/* second call, one page, without hint */
map_hint = 0;
printf("=> calling mmap without hint, size = %zu\n", map_size);
addr = mmap(map_hint, map_size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (addr == MAP_FAILED) {
printf("mmap failed: %s\n", strerror(errno));
}
else {
printf("mmap succeeded: addr = %p\n", addr);
#ifdef SLEEP
/* leave time to use 'procstat -v' */
sleep(10);
#endif
if(munmap(addr, map_size) != 0) {
printf("munmap failed: %s\n", strerror(errno));
}
}
return (0);
}
8< ----------- >8
and its output :
1) On an i386 machine, FreeBSD 8.2-RELEASE :
$ ./test-mmap
=> calling mmap with hint = 0x20000000, size = 4096
mmap succeeded: addr = 0x281a8000
=> calling mmap without hint, size = 4096
mmap succeeded: addr = 0x281a8000
$ procstat -v 1685
PID START END PRT RES PRES REF SHD FL TP PATH
1685 0x8048000 0x8049000 r-x 1 0 1 0 CN vn /tmp/test-mmap
1685 0x8049000 0x8100000 rw- 1 0 1 0 -- df
1685 0x28049000 0x28078000 r-x 47 0 82 41 CN vn /libexec/ld-elf.so.1
1685 0x28078000 0x2807a000 rw- 2 0 1 0 C- vn /libexec/ld-elf.so.1
1685 0x2807a000 0x2808d000 rw- 12 0 1 0 -- df
1685 0x2808d000 0x2818b000 r-x 134 0 82 41 CN vn /lib/libc.so.7
1685 0x2818b000 0x28191000 rw- 6 0 1 0 C- vn /lib/libc.so.7
1685 0x28191000 0x281a8000 rw- 5 0 1 0 -- df
1685 0x281a8000 0x281a9000 rwx 0 0 0 0 -- --
1685 0x28200000 0x28300000 rw- 2 0 1 0 -- df
1685 0xbfbe0000 0xbfc00000 rwx 3 0 1 0 -- df
2) On an amd64 machine, FreeBSD 8.2-RELEASE :
$ ./test-mmap
=> calling mmap with hint = 0x20000000, size = 4096
mmap succeeded: addr = 0x800538000
=> calling mmap without hint, size = 4096
mmap succeeded: addr = 0x800538000
$ procstat -v 38899
PID START END PRT RES PRES REF SHD FL TP PATH
38899 0x400000 0x401000 r-x 1 0 1 0 CN vn
/tmp/test-mmap
38899 0x500000 0x600000 rw- 2 0 1 0 -- df
38899 0x800500000 0x800530000 r-x 48 0 218 95 CN vn
/libexec/ld-elf.so.1
38899 0x800530000 0x800538000 rw- 7 0 2 0 -- df
38899 0x800538000 0x800539000 rwx 0 0 2 0 -- df
38899 0x80062f000 0x800637000 rw- 8 0 1 0 C- vn
/libexec/ld-elf.so.1
38899 0x800637000 0x800646000 rw- 5 0 1 0 -- df
38899 0x800646000 0x80074e000 r-x 146 0 218 95 CN vn
/lib/libc.so.7
38899 0x80074e000 0x80084e000 --- 0 0 2 0 -- df
38899 0x80084e000 0x80086d000 rw- 31 0 1 0 C- vn
/lib/libc.so.7
38899 0x80086d000 0x800888000 rw- 6 0 2 0 -- df
38899 0x800a00000 0x800c00000 rw- 5 0 1 0 -- df
38899 0x7ffffffe0000 0x800000000000 rwx 3 0 1 0 -- df
Using MAP_FIXED, I can get the desired address, but it is overkill (it
replaces
any previous mappings and its use is discouraged, see mmap(2)) and
should not
be needed here.
Am I doing something wrong here ?
--
Ganael LAPLANCHE <ganael.laplanche at martymac.org>
http://www.martymac.org | http://contribs.martymac.org
FreeBSD: martymac <martymac at FreeBSD.org>, http://www.FreeBSD.org
More information about the freebsd-stable
mailing list