之前实习做了一个项目,大致意思是将实时行情数据用mmap高效存储起来,策略同学也会及时(延时在3min内)读取。
面试官拷打的角度无非几个:

  1. 你讲讲什么是mmap,为什么叫内存映射文件,内存指的是什么
  2. 为什么要使用mmap,和普通的IO操作有什么区别,节省了什么
  3. 为什么不用共享内存/缓存来处理
    针对这几个问题重新认真总结下mmap到底是什么

文件IO操作

https://zhuanlan.zhihu.com/p/366964820
https://www.cnblogs.com/huxiao-tee/p/4657851.html

  1. 在发起read/write操作后,用户进程会提出一个系统调用,进入内核态。
  2. 内核查找进程文件表符,定位到内核已打开文件集上文件信息,获得inode(inode就是单个文件的信息,类似进程的PCB)
  3. inode在address_space上查找要请求的文件页,查看是否在page cache里,如果在就直接返回该页内容
  4. 若不存在,则用inode定位文件磁盘地址,将数据从磁盘copy到Page cache里。然后再次发起读页面操作,将页面缓存数据发给用户进程
  5. page cache被拷贝到用户空间后,用户进行读写操作,写操作还需要额外写回page cache。
    可以看到,无论是否命中cache,都需要用户形态切换内核形态,然后将page cache内容复制进用户空间。并且根据写回策略的不同,a进程想修改文件,但还没写回。b进程想读a修改后最新的内容是很难做到的。
    在这里插入图片描述

mmap

mmap即是内存映射文件。首先理解什么是内存映射,是指的是用户空间将一段内存区域映射到内核空间,这样的好处是用户在修改的时候可以直接反映到内核,同时内核的修改也能直接反映到内存空间,有共享内存的意思在。至于它和共享内存有什么优劣之分,后面会提到。
既然内存映射是将用户空间一段内存区域映射到内核空间,那么内存映射文件就是说将一个文件映射到进程的地址空间,让文件磁盘地址和进程虚拟地址进行映射,实现了用户空间和内核数据的直接交互,而省去了空间不同数据不通的繁琐过程
在这里插入图片描述
page cache
在这里插入图片描述
所以问题来了,mmap是如何实现的呢?其实就是虚拟内存地址->内核空间的page cache建立了映射,我们用着虚拟内存的地址就能直接去操作page cache,减少了系统调用的次数。
这恰好回答了mmap和普通IO的区别:减少了用户态向内核态的切换和拷贝,普通IO需要copy page cache到用户空间,用户空间改完了再copy到page cache里。但是mmap直接省去这一步,直接操作,这也使得其他进程也能可见到修改。

问题答疑

1和2在前面的叙述已经解释,那么mmap比共享内存好在哪里:

  1. 灵活性:mmap有灵活的映射方式
  2. 以文件的形式组织,还能支持写回文件,比共享内存更适合该场景
  3. 以开头的场景而言,策略同学对数据的实时性需求也没有那么强,如果用共享内存来交互,策略同学读的速度不一定跟得上我们更新的速度,很有可能造成共享内存无休止增长。而使用mmap来说,如果page cache失效了,还能去文件里加载再读
Logo

更多推荐