本文主要供C/C++开发人员参考,其他技术人员酌情自取。
文件预读和缓存机制在Linux下是默认开启的。对于随机读,预读机制往往会导致读放大。如果应用程序自己实现了数据缓存,通常就不再需要操作系统提供的文件内容缓存,比如数据库。
Linux下有两种方法可以禁用文件预读和文件缓存机制。
第一种方法是使用 direct IO,这种方式操作系统既不会预读,也不会启用文件缓存。调用open函数时将flags参数加上标记位O_DIRECT即可,简单直接有没有?噢,No!这只是万里长征第一步,direct IO的噩梦在于:读写buffer的内存地址、文件偏移量和读写长度都需要按设备的block size(注意:block size通常为512,不是通常为4KB的page size)对齐!对于数据读取,对齐后可能会多读出一些数据,返回对应位置和长度的数据即可。对于数据写入,如果程序天然按对齐方式写入,比如数据库,此时不需要额外处理,否则就是噩梦了。如果支持任意偏移量和长度写入,对于原地修改数据的方式,需要读出原有数据和新数据组合,然后以对齐方式写入。而对于追加写入方式,如果不做合并写的话,可能存在明显浪费硬盘空间的问题。
第二种方法是使用函数 posix_fadvise,函数原型为:int posix_fadvise(int fd, off_t offset, off_t len, int advice); 其中的参数len取值为0,表示针对整个文件。advice为POSIX_FADV_RANDOM 关闭预读机制,为POSIX_FADV_DONTNEED清除文件缓存。POSIX_FADV_RANDOM要在打开文件后立即设置(即事前设置),而POSIX_FADV_DONTNEED是清除缓存操作,在需要时调用(即事后调用),比如写完一个文件后在close之前调用。如何在事前禁用Linux的文件缓存,有知道的朋友请不吝赐教。