前面有童鞋在微信群里面问mmap,然后敲了很多字,不想浪费,把这些字搬家到公众号。
本文总结归纳mmap的数种情况,进行一个归类。
我们都知道,Linux一个进程使用的内存分为2种:
file-backed pages(有文件背景的页面,比如代码段、比如read/write方法读写的文件、比如mmap读写的文件;他们有对应的硬盘文件,因此如果要交换,可以直接和硬盘对应的文件进行交换),此部分页面进page cache
anonymous pages(匿名页,如stack,heap,CoW后的数据段等;他们没有对应的硬盘文件,因此如果要交换,只能交换到虚拟内存-swapfile或者Linux的swap硬盘分区),此部分页面,如果系统内存不充分,可以被swap到swapfile或者硬盘的swap分区
下面我们看看,mmap的各种情况,与上面的页面类型之间的关系。
不映射任何文件(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.1 共享映射: 这个时候页面dirty后要回写磁盘,是有文件背景(file-backed)的页面
2.2 私有映射:这个时候是CoW(写时拷贝)页面,最后变成匿名页
映射tmpfs文件,一般做进程间共享内存通信用(不需要亲缘关系),以共享方式映射,看起来是类似2.1有file-backed,但是file本身也是内存,所以本质上面还是匿名页,代码实例:
映射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 );
我今天才知道,我之所以漂泊就是在向你靠近。
--《廊桥遗梦》