前面有童鞋在微信群里面问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本身也是内存,所以本质上面还是匿名页,代码实例:


    宋宝华: Linux mmap的多种情况和背后的差异-LMLPHP


  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 );

宋宝华: Linux mmap的多种情况和背后的差异-LMLPHP宋宝华: Linux mmap的多种情况和背后的差异-LMLPHP

我今天才知道,我之所以漂泊就是在向你靠近。

--《廊桥遗梦》


12-27 04:34