本文同步自(如浏览不正常请点击跳转):https://zohead.com/archives/vmtouch-code-analysis/ vmtouch 是一个 portable 的 page cache 诊断和控制工具,可以查看文件或者设备中有多少在 page cache 中,知道之后对这些在 page cache 中的内存引用可以避免 page fault,支持将文件的内容从 page cache 逐出,同时还可以将文件手工 touch 到 page cache 中,支持 lock 文件部分区域到 memory 中防止被交换出去从而提高。 vmtouch 可以在 Linux、BSD 等系统上使用,在这下载编译: http://hoytech.com/vmtouch/ 今天简单看了下 vmtouch 的代码,发现还比较简单,自己写个类似的程序验证之后,将代码分析结果写下。vmtouch 的代码比较少,我只贴出最关键的一个函数 vmtouch_file(关键部分已经高亮显示),这个函数做 分析 page cache 使用、touch、lock 的操作,其它部分只是加了读了目录的遍历处理之类的。 稍微有点基础就可以看明白了,先 mmap 映射文件到当前进程,按 page size 对齐之后,调用 mincore 函数就可以得到文件中每一个 page 是否在 page cache 中,结果保存在 mincore_array 数组中,该数据中每个字节的第一位即表示是否在 page cache 中。 将文件内容逐出(指定 o_evict)出 page cache 是通过 posix_fadvise 函数调用 fadvise 系统调用来实现的(BSD通过 msync 实现,这个在 Linux 上没有效果)。fadvise 系统调用可以告诉 kernel 要操作的文件在接下来要干什么,kernel 可以提前做一些操作而提高性能,Linux kernel 里实现了以下几种控制方式: POSIX_FADV_NORMAL - 正常操作,对文件使用底层设备的默认 readahead 值; POSIX_FADV_SEQUENTIAL - 顺序I/O,对文件使用两倍的 readahead 值; POSIX_FADV_RANDOM - 随机I/O,禁用文件上的 readahead; POSIX_FADV_NOREUSE - 只使用一次 POSIX_FADV_WILLNEED - 很快需要使用,对文件使用非阻塞读到 page cache POSIX_FADV_DONTNEED - 不再需要使用文件,从 page cache 中逐出 posix_fadvise 加 POSIX_FADV_DONTNEED 参数就可以将文件从 page cache 中逐出,需要注意的是如果需要确保文件从 page cache 中逐出,还需要在调用 fadvise 之前用 fsync/fdatasync/sync_file_range 之类的函数将 dirty page 清理。 下面是我在 Linux 下用 posix_fadvise 的一个测试程序测试的结果: 从 free 命令的结果可以很明显的看到,dd 之后基本文件都在 page cache 中,fadvise 之后从 page cache 中正确逐出。 接着是 vmtouch 中的 touch 操作(指定 o_touch)就更简单了,对 mmap 到的地址直接遍历引用,不在 page cache 的内容会自动产生 page fault 到 page cache 中。 lock 内存(指定 o_lock)也则直接使用 mlock 函数来实现,mlock 对于对安全性和实时性有很高要求的程序非常有用,可以保证指定的文件区域在内存中,不被 swap 出去。 以上为个人分析结果,有任何问题欢迎指正咯 ^_^