参考文献:html
《从内核文件系统看文件读写过程》http://www.cnblogs.com/huxiao-tee/p/4660352.html?utm_source=tuicool&utm_medium=referralnode
《mmap是什么》http://www.cnblogs.com/huxiao-tee/p/4660352.html?utm_source=tuicool&utm_medium=referrallinux
正文:算法
首先说一下文件系统,Linux文件系统的三层结构想必你们多少都了解一些,每一个进程中都有一个用户文件描述符表,表项指向一个全局的文件表中的某个表项,文件表表项有一个指向内存inode的指针,每一个inode惟一标识一个文件。若是同时有多个进程打开同一文件,他们的用户文件描述符表项指向不一样的文件表项,可是这些文件表项会指向同一个inode。缓存
此时又会引出另一个东东:page cache。内核会为每一个文件单独维护一个page cache,用户进程对于文件的大多数读写操做会直接做用到page cache上,内核会选择在适当的时候将page cache中的内容写到磁盘上(固然咱们能够手工fsync控制回写),这样能够大大减小磁盘的访问次数,从而提升性能。Page cache是linux内核文件访问过程当中很重要的数据结构,page cache中会保存用户进程访问过得该文件的内容,这些内容以页为单位保存在内存中,当用户须要访问文件中的某个偏移量上的数据时,内核会以偏移量为索引,找到相应的内存页,若是该页没有读入内存,则须要访问磁盘读取数据。为了提升页得查询速度同时节省page cache数据结构占用的内存,linux内核使用树来保存page cache中的页。安全
在了解了以上的基础以后,咱们就来比较一下mmap和read/write的区别,先说一下read/write系统调用,read/write系统调用会有如下的操做:数据结构
整个过程仍是比较艰辛的,基本上涉及到用户内核态的切换,还有就是数据拷贝接下来继续说mmap吧,mmap系统调用是将硬盘文件映射到用内存中,说的底层一些是将page cache中的页直接映射到用户进程地址空间中,从而进程能够直接访问自身地址空间的虚拟地址来访问page cache中的页,这样会并涉及page cache到用户缓冲区之间的拷贝,mmap系统调用与read/write调用的区别在于:post
从上所述,当频繁对一个文件进行读取操做时,mmap会比read高效一些。性能
最后再说一下page cache的话题,从上面所说咱们从磁盘文件中读取的内容都会存在page cache中,但当咱们关闭这个文件时,page cache中内容会立马释放掉吗?答案是否,磁盘的读取速度比内存慢太多,若是能命中page cache能够显著提高性能,万一后续又有对这个文件的操做,系统就能够很快速的响应。固然,这些文件内容也不是一直存在page cache中的,通常只要系统有空闲物理内存,内核都会拿来当缓存使用,但当物理内存不够用,内存会清理出部分page cache应急,这也就是告诉咱们程序对于物理内存的使用能省则省,交给内核使用,做用很大。ui
还有就是普通的write调用只是将数据写到page cache中,并将其标记为dirty就返回了,磁盘I/O一般不会当即执行,这样作的好处是减小磁盘的回写次数,提供吞吐率,不足就是机器一旦意外挂掉,page cache中的数据就会丢失。通常安全性比较高的程序会在每次write以后,调用fsync当即将page cache中的内容回写到磁盘中。