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_EXEC:表示映射的页面是可以执行的 。
- PROT_READ:表示映射的页面是可以读取的 。
- PROT_WRITE:表示映射的页面是可以写入的 。
- PROT_NONE:表示映射的页面是不可访问的 。
- MAP_SHARED:创建一个共享映射的区域 。多个进程可以通过共享映射方式来映射一个文件,这样其他进程也可以看到映射内容的改变,修改后的内容会同步到磁盘文件中 。
- MAP_PRIVATE:创建一个私有的写时复制的映射 。多个进程可以通过私有映射的方式来映射一个文件,这样其他进程不会看到映射内容的改变,修改后的内容也不会同步到磁盘文件中 。
- MAP_ANONYMOUS:创建一个匿名映射,即没有关联到文件的映射 。
- MAP_FIXED:使用参数addr创建映射,如果内核无法映射指定地址addr,那么mmap会返回失败,参数addr要求按页对齐 。如果addr和length指定的进程地址空间和已有的VMA区域重叠,那么内核会调用do_munmap()函数把这段重叠区域销毁,然后重新映射新的内容 。
- MAP_POPULATE:对于文件映射来说,会提前预读文件内容到映射区域,该特性只支持私用映射 。
- 匿名映射:没有映射对应的相关文件,这种映射的内存区域的内容会被初始化为0 。
- 文件映射:映射和实际文件相关联,通常是把文件的内容映射到进程地址空间,这样应用程序就可以像操作进程地址空间一样读写文件 。

文章插图
- 私有匿名映射
- 共享匿名映射
创建共享匿名映射有如下两种方式:
(1)fd=-1且flags= MAP_ANONYMOUS|MAP_SHARED 。在这种情况下,do_mmap_pgoff()->mmap()函数最终调用shmem_zero_setup()来打开一个"/dev/zero"特殊的设备文件 。
(2)另外一个是直接打开"/dev/zero"设备文件,然后使用这个文件句柄来创建mmap 。
- 私有文件映射
私有文件映射的最常用的场景是加载动态共享库 。
- 共享文件映射
(1)读写文件:
把文件内容映射到进程地址空间,同时对映射的内容做了修改,内核的回写机制(writeback)最终会把修改的内容同步到磁盘中 。
(2)进程间通信:
进程之间的进程地址空间相互隔离,一个进程不能访问到另外一个进程的地址空间 。如果多个进程都同时映射到一个相同的文件,就实现了多进程间的共享内存的通信 。如果一个进程对映射内容做了修改,那么另外的进程是可以看到的 。
推荐阅读
- 分布式协议与算法,你了解多少?
- SSH只能用于远程Linux主机?那说明你见识太小了
- 存在外星人的有力证据 宇宙中外星人真的存在吗?
- 外星人就在你身边 外星人隐藏在人类中间
- 你平时是怎么管理 Docker 容器的?还在使用一大堆的窗口和命令吗
- 地球上之所以有生命存在,至少是因为 你认为地球以外是否有生命存在
- 他来自外星 你觉得倘若外星人存在,它们是友好的吗?
- 带你一步步解析 HTTP
- 穿衣搭配|职场女性穿衣有段位,从配色上就能分高下,看看你是青铜还是黄金
- 陕西村庄离奇消失真相 1987年陕西一个村庄离奇消失是真的
