简析Linux mmap知识点

一、I/O 的三种方式

简析Linux mmap知识点

  • 标准 I/O:平时用到 read/write 操作都属于标准 I/O,也就是缓存 I/O(Buffered I/O)。
  • mmap:由于与Page Cache做过内存映射,只需要从磁盘拷贝一次,不需要再拷贝回用户空间。
  • 直接 I/O:减少了一次数据拷贝和一些系统调用的耗时,很大程度降低了 CPU 的使用率以及内存的占用,在 open() 文件的时候需要指定 O_DIRECT 参数。

二、什么是虚拟地址空间

简析Linux mmap知识点

在Linux上为了做进程隔离,让每个进程都运行在自己的单独的虚拟地址空间,同时由于物理内存容量有限,所以每个进程使用虚拟内存地址来隔离,但又共享物理内存。

在32位的Linux内核中,每个进程都有4G的虚拟地址空间,其中3G用户空间,1G内核空间。每个进程都拥有独自的用户空间,共享内核空间,我们平时在代码里获取的地址就是虚拟地址。

三、什么是内存映射

简析Linux mmap知识点

虚拟内存分割为大小固定的块,称作虚拟页(Virtual Page,VP),一般情况下,每个虚拟页的大小默认是4KB。物理内存也被分割为大小固定的块,称作物理页(Physical Page,PP),其大小默认也是4KB。

每个进程都有独立的虚拟地址空间,它们都有独立的页表数据,通过页表和MMU将虚拟地址映射到物理地址,然后把映射的文件内容读入到物理内存中,这样就把内存与文件的映射关系建立起来,对映射的内存区进行读写操作实际上就是对文件的读写操作,该过程默认是非同步的。

四、mmap映射

简析Linux mmap知识点

  • 私有文件映射

多个进程使用同样的物理内存页进行初始化,但是各个进程对内存文件的修改不会共享,也不会反应到物理文件中。

  • 私有匿名映射

创建一个新的、各个进程不共享的映射,这种使用主要用于分配内存(malloc分配大内存会调用mmap)。
例如开辟新进程时,会为每个进程分配虚拟的地址空间,这些虚拟地址映射的物理内存空间各个进程间读的时候共享,写的时候会copy-on-write。

  • 共享文件映射

多个进程通过虚拟内存技术共享相同的物理内存空间,对内存文件的修改会反应到实际物理文件中,这是进程间通信(IPC)的一种机制。

  • 共享匿名映射

这种机制在进行fork的时候不会采用写时复制,父子进程完全共享同样的物理内存页,这也就实现了父子进程通信(IPC)。

 

参考:

https://time.geekbang.org/column/article/75760

https://zhuanlan.zhihu.com/p/67894878

https://www.jianshu.com/p/755338d11865