mmap/munmap接口是用户空间的最经常使用的一个系统调用接口,不管是在用户程序中分配内存、读写大文件,连接动态库文件,仍是多进程间共享内存,均可以看到mmap/munmap的身影。mmap/munmap函数声明以下:数组
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length);
prot参数一般表示映射页面的的读写权限,能够有以下参数组合:函数
flags参数也是一个重要的参数,有以下常见的参数:code
参数fd能够看出mmap映射是否和文件相关联,所以Linux内核中映射能够分为匿名映射和文件映射。接口
最后根据文件关联性和映射区域是否共享等属性,又能够分为以下4种,见表2.1。进程
mmap映射类型内存
映射类型 | 映射类型 | |
---|---|---|
私有映射 | 共享映射 | |
匿名映射 | 私有匿名映射-一般用于内存分配 | 共享匿名映射-一般用于进程间共享内存 |
文件映射 | 私有文件映射-一般用于加载动态库 | 共享文件映射-一般用于内存映射IO,进程间通讯 |
当使用参数fd=-1且flags=MAP_ANONYMOUS | MAP_PRIVATE时,建立的mmap映射是私有匿名映射。私有匿名映射最多见的用途是在glibc分配大块内存中,当须要的分配的内存大于MMAP_THREASHOLD(128KB)时,glibc会默认使用mmap代替brk来分配内存。同步
当使用参数fd=-1且flags=MAP_ANONYMOUS | MAP_SHARED。在这种状况下,建立共享匿名映射。共享匿名映射让相关进程共享一块内存区域,一般用于父子进程的之间通讯。it
建立共享匿名映射有以下两种方式:table
(1)fd=-1且flags= MAP_ANONYMOUS|MAP_SHARED。在这种状况下,do_mmap_pgoff()->mmap()函数最终调用shmem_zero_setup()来打开一个"/dev/zero"特殊的设备文件。多进程
(2)另一个是直接打开"/dev/zero"设备文件,而后使用这个文件句柄来建立mmap。
私有文件映射时flags的标志位被设置为MAP_PRIVATE,那么就会建立私有文件映射。
私有文件映射的最经常使用的场景是加载动态共享库。
建立文件映射时flags的标志位被设置为MAP_SHARED,那么就会建立共享文件映射。若是prot参数指定了PROT_WRITE,那么打开文件须要制定O_RDWR标志位。共享文件映射一般有以下场景:
(1)读写文件:
把文件内容映射到进程地址空间,同时对映射的内容作了修改,内核的回写机制(writeback)最终会把修改的内容同步到磁盘中。
(2)进程间通讯:
进程之间的进程地址空间相互隔离,一个进程不能访问到另一个进程的地址空间。若是多个进程都同时映射到一个相同的文件,就实现了多进程间的共享内存的通讯。若是一个进程对映射内容作了修改,那么另外的进程是能够看到的。