原创 宋宝华 Linux阅码场 2018-03-05


前面有童鞋在微信群里面问mmap,然后敲了很多字,不想浪费,把这些字搬家到公众号。 本文总结归纳mmap的数种情况,进行一个归类。


我们都知道,Linux一个进程使用的内存分为2种:

  1. file-backed pages(有文件背景的页面,比如代码段、比如read/write方法读写的文件、比如mmap读写的文件;他们有对应的硬盘文件,因此如果要交换,可以直接和硬盘对应的文件进行交换),此部分页面进page cache
  2. anonymous pages(匿名页,如stack,heap,CoW后的数据段等;他们没有对应的硬盘文件,因此如果要交换,只能交换到虚拟内存-swapfile或者Linux的swap硬盘分区),此部分页面,如果系统内存不充分,可以被swap到swapfile或者硬盘的swap分区

下面我们看看,mmap的各种情况,与上面的页面类型之间的关系。

1. 不映射任何文件(MAP_ANONYMOUS),又分为私有和共享映射2种情况:

1.1 私有映射(MAP_PRIVATE) 这个是malloc库函数之类底层的实现之一,最后对应匿名页。 比如应用程序调用:

int *p= malloc(1024*1024*80);

对应的系统调用是:

mmap2(NULL, 83890176, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)

1.2 共享映射MAP_SHARED 用作有亲缘关系进程间的共享内存通信,最后对应匿名页。

2.映射磁盘里面的文件,又分为共享映射和私有映射

2.1 共享映射: 这个时候页面dirty后要回写磁盘,是有文件背景(file-backed)的页面 2.2 私有映射:这个时候是CoW(写时拷贝)页面,最后变成匿名页

3.映射tmpfs文件,

一般做进程间共享内存通信用(不需要亲缘关系),以共享方式映射,看起来是类似2.1有file-backed,但是file本身也是内存,所以本质上面还是匿名页,代码实例:

4.映射framebuffer等,

显存,多媒体,这些是为了减少一次用户空间往内核空间的内存拷贝。这个时候mmap对应的文件是/dev/下面的设备文件。代码案例:

int fb;
unsigned char* fb_mem;
fb = open ("/dev/fb0", O_RDWR);
fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
memset (fb_mem, 0, 1024*768 );