用处:
1、分配内存,一般是超过128K的malloc会使用mmap的系统调用
2、读写大文件
3、链接动态库文件
4、多进程间共享内存
Linux头文件: #include<sys/mman.h>
安卓C库文件:android/bionic/libc/bionic/mmap.cpp
void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset)
int munmap(void* __addr, size_t __size);
mmap -> mmap64
参数介绍:
addr:用于指定映射到进程虚拟空间的起始地址,为了提高可移植性,一般设为NULL,让内核分配合适的地址
size:映射到进程地址空间的大小
prot:内存映射区域的读写属性(PROT_EXRC/PROT_READ/PROT_WRITE/PROT_NONE)
flags:内存映射的属性,如共享映射,私有映射
- MAP_SHARED:创建一个共享映射区域,多个进程可以通过共享映射方式来映射一个文件,修改后的内容会同步到磁盘
- MAP_PRIVATE:私有写时复制的映射,多个进程可以通过私有映射方式来映射一个文件,修改后的内容不会同步到磁盘
- MAP_ANONYMOUS:没有关联到文件的映射
- MAP_FIXED:使用参数addr创建映射,按页对齐,如果addr+length和已有VMA重叠,则销毁重新映射
- MAP_POPULATE:文件映射提前预读内容,只支持私有映射
fd:文件映射的句柄
offset:文件映射时的偏移量
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
errno = EINVAL;
return MAP_FAILED;
}
// prevent allocations large enough for `end - start` to overflow
size_t rounded = __BIONIC_ALIGN(size, PAGE_SIZE);
if (rounded < size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
bool is_private_anonymous =
(flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
is_private_anonymous && !is_stack_or_grows_down) {
ErrnoRestorer errno_restorer;
int rc = madvise(result, size, MADV_MERGEABLE);
if (rc == -1 && errno == EINVAL) {
kernel_has_MADV_MERGEABLE = false;
}
}
return result;
}
来了,排列组合
- 私有匿名映射,fd=-1, flags=MAP_ANONYMOUS|MAP_PRIVATE, glibc分配大内存块(超过128K)代替brk
- 共享匿名映射,fd=-1,,flags=MAP_ANONYMOUS|MAP_SHARED,常用于父子进程通信,共享一块内存区域
- 私有文件映射,MAP_PRIVATE,加载动态共享库
- 共享文件映射,1.读写文件 2.进程间通信