mmap概述

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);
  • addr:用于指定映射到进程空间的起始地址,为了应用程序的可移植性,通常设置为NULL,让内核来选择一个合适的地址。
  • length:表示映射到进程地址空间的大小
  • prot:用于设置内核映射区域的读写属性等。
  • flags:用于设置内存映射的属性,例如共享映射、私有映射等。
  • fd:表示这个是一个文件映射,fd是打开文件的句柄。
  • offset:在文件映射时,表示文件的偏移量。

prot参数一般表示映射页面的的读写权限,能够有以下参数组合:函数

  • PROT_EXEC:表示映射的页面是能够执行的。
  • PROT_READ:表示映射的页面是能够读取的。
  • PROT_WRITE:表示映射的页面是能够写入的。
  • PROT_NONE:表示映射的页面是不可访问的。

flags参数也是一个重要的参数,有以下常见的参数:code

  • MAP_SHARED:建立一个共享映射的区域。多个进程能够经过共享映射方式来映射一个文件,这样其余进程也能够看到映射内容的改变,修改后的内容会同步到磁盘文件中。
  • MAP_PRIVATE:建立一个私有的写时复制的映射。多个进程能够经过私有映射的方式来映射一个文件,这样其余进程不会看到映射内容的改变,修改后的内容也不会同步到磁盘文件中。
  • MAP_ANONYMOUS:建立一个匿名映射,即没有关联到文件的映射。
  • MAP_FIXED:使用参数addr建立映射,若是内核没法映射指定地址addr,那么mmap会返回失败,参数addr要求按页对齐。若是addr和length指定的进程地址空间和已有的VMA区域重叠,那么内核会调用do_munmap()函数把这段重叠区域销毁,而后从新映射新的内容。
  • MAP_POPULATE:对于文件映射来讲,会提早预读文件内容到映射区域,该特性只支持私用映射。

参数fd能够看出mmap映射是否和文件相关联,所以Linux内核中映射能够分为匿名映射和文件映射。接口

  • 匿名映射:没有映射对应的相关文件,这种映射的内存区域的内容会被初始化为0。
  • 文件映射:映射和实际文件相关联,一般是把文件的内容映射到进程地址空间,这样应用程序就能够像操做进程地址空间同样读写文件。

最后根据文件关联性和映射区域是否共享等属性,又能够分为以下4种,见表2.1。进程

​ mmap映射类型内存

映射类型 映射类型
私有映射 共享映射
匿名映射 私有匿名映射-一般用于内存分配 共享匿名映射-一般用于进程间共享内存
文件映射 私有文件映射-一般用于加载动态库 共享文件映射-一般用于内存映射IO,进程间通讯
  1. 私有匿名映射

当使用参数fd=-1且flags=MAP_ANONYMOUS | MAP_PRIVATE时,建立的mmap映射是私有匿名映射。私有匿名映射最多见的用途是在glibc分配大块内存中,当须要的分配的内存大于MMAP_THREASHOLD(128KB)时,glibc会默认使用mmap代替brk来分配内存。同步

  1. 共享匿名映射

当使用参数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。

  1. 私有文件映射

私有文件映射时flags的标志位被设置为MAP_PRIVATE,那么就会建立私有文件映射。

私有文件映射的最经常使用的场景是加载动态共享库。

  1. 共享文件映射

建立文件映射时flags的标志位被设置为MAP_SHARED,那么就会建立共享文件映射。若是prot参数指定了PROT_WRITE,那么打开文件须要制定O_RDWR标志位。共享文件映射一般有以下场景:

(1)读写文件:

把文件内容映射到进程地址空间,同时对映射的内容作了修改,内核的回写机制(writeback)最终会把修改的内容同步到磁盘中。

(2)进程间通讯:

进程之间的进程地址空间相互隔离,一个进程不能访问到另一个进程的地址空间。若是多个进程都同时映射到一个相同的文件,就实现了多进程间的共享内存的通讯。若是一个进程对映射内容作了修改,那么另外的进程是能够看到的。

相关文章
相关标签/搜索