PageCache和mmap

文章是抄的,https://www.jianshu.com/p/7044e0b9ab7a?from=singlemessage

pagecache

linux对文件的读写必须先走pagecache,pagecache是内存中的一块区域,这样做的好处是,在写入的时候不直接写入硬盘,而是写入内存,可以加速读写。后续操作系统会自动把其内容刷到硬盘上。
例如我们调用操作系统的write函数,直接写入到pagecache中而不是磁盘中。后续会将数据拷贝到内核态,再拷贝到硬盘上,这个过程操作系统可以为我们完成,当然我们我们也可以手动执行刷盘。

mmap

这里就要介绍一下mmap的优点了,mmap和write/read一样需要从pagecache中进行刷盘,但是mmap的好处就是减少了一次数据复制,直接将pagecache刷到硬盘上而不需要经过内核态。

最后再说一下page cache的话题,从上面所说我们从磁盘文件中读取的内容都会存在page cache中,但当我们关闭这个文件时,page cache中内容会立马释放掉吗?答案是否,磁盘的读取速度比内存慢太多,如果能命中page cache可以显著提升性能,万一后续又有对这个文件的操作,系统就可以很快速的响应。当然,这些文件内容也不是一直存在page cache中的,一般只要系统有空闲物理内存,操作系统都会拿来当缓存使用,但当物理内存不够用,内存会清理出部分page cache应急。

还有就是普通的write调用只是将数据写到page cache中,并将其标记为dirty就返回了,磁盘I/O通常不会立即执行,这样做的好处是减少磁盘的回写次数,提供吞吐率,不足就是机器一旦意外挂掉,page cache中的数据就会丢失。一般安全性比较高的程序会在每次write之后,调用fsync立即将page cache中的内容回写到磁盘中。

DirectIo

哈哈,看到了这里,没想到还有一种刷盘方式吧?对,就是dio。从上面我们可以看出来,操作系统为了保持自身的稳定、安全性,使用了页式管理或者内核态拷贝。这里我们单看mmap所带来的问题。可以说mmap是一种比较快的落盘方式了。但是由于linux本身用的还是页式管理(mmap一样),它不可避免的会导致缺页中断的现象,这时候会进行页面置换算法,想想还是有点耗时的。
对此,linux本身提供了dio的接口,使得数据直接从应用程序地址空间落到硬盘上。当然这里如果要加快读写,可以自己设定缓冲区,而不是用pagecache,例如数据库管理系统的实现


我的理解是
  PageCache是linux系统必定使用的,我们调用java去写磁盘都不是直接写磁盘,而是写PageCache,pageCache会自动帮我们落盘。但是PageCache还是有一次,用户态到内核态的数据拷贝,因此效率上不是特别高。
  MMAP是内存和磁盘的映射,这样pageCache的数据直接落盘,而不再需要那一次的用户态内核态拷贝。
  至于java中的mmap就是这样的
MappedByteBuffer buffer = fc.map(MapMode.READ_WRITE, 0, 1000);  
       for (int i = 0;i< 100000;i++){  
           buffer.put((byte)65);  
       }  

  fc是FileChannel

posted on 2021-03-17 16:15  MaXianZhe  阅读(2104)  评论(0编辑  收藏  举报

导航