Linux的Cache和Buffer理解( 四 )

看到这里我们就明白了:为什么使用了posix_fadvise后相关的内存没有被释放出来:页面还脏是最关键的因素 。
但是我们如何保证页面全部不脏呢?fdatasync或者fsync都是选择,或者Linux下新系统调用sync_file_range都是可用的 , 这几个都是使用WB_SYNC_ALL模式强制要求回写完毕才返回的 。所以应该这样做:
fdatasync(fd);posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);总结:
使用posix_fadvise可以有效的清除page cache , 作用范围为文件级 。下面给出应用程序编程建议:

  • 用于测试I/O的效率时 , 可以用posix_fadvise来消除cache的影响;
  • 当确认访问的文件在接下来一段时间不再被访问时 , 很有必要调用posix_fadvise来避免占用不必要的可用内存空间 。
  • 若当前系统内存十分紧张时 , 且在读写一个很大的文件时 , 为避免OOM风险 , 可以分段边读写边清cache , 但也直接导致性能的下降 , 毕竟空间和时间是一对矛盾体 。
1.3 使用vmtouch控制Cachevmtouch是一个可移植的文件系统cahce诊断和控制工具 。近来该工具被广泛使用 , 最典型的例子是:移动应用Instagram(照片墙)后台服务端使用了vmtouch管理控制page cache 。了解vmtouch原理及使用可以为我们后续后端设备所用 。
快速安装指南:
$ git clone https://github.com/hoytech/vmtouch.git$ cd vmtouch$ make$ sudo make installvmtouch用途:
1、 查看一个文件(或者目录)哪些部分在内存中;
2、 把文件调入内存;
3、 把文件清除出内存 , 即释放page cache;
4、 把文件锁住在内存中而不被换出到磁盘上;
5、 ……
vmtouch实现:
其核心分别是两个系统调用 , mincore和posix_fadvise 。两者具体使用方法使用man帮助都有详细的说明 。posix_fadvise已在上文提到 , 用法在此不作说明 。简单说下mincore:
NAME mincore - determine whether pages are resident in memory SYNOPSIS #include <unistd.h> #include <sys/mman.h>int mincore(void *addr, size_t length, unsigned char *vec);Feature Test macro Requirements for glibc (see feature_test_macros(7)):mincore(): _BSD_SOURCE || _SVID_SOURCEmincore需要调用者传入文件的地址(通常由mmap()返回) , 它会把文件在内存中的情况写在vec中 。
vmtouch工具用法:
Usage: vmtouch [OPTIONS] ... FILES OR DIRECTORIES ...
 
Options:
-t touch pages into memory
-e evict pages from memory
-l lock pages in physical memory with mlock(2)
-L lock pages in physical memory with mlockall(2)
-d daemon mode
-m <size> max file size to touch
-p <range> use the specified portion instead of the entire file
-f follow symbolic links
-h also count hardlinked copies
-w wait until all pages are locked (only useful together with -d)
-v verbose
-q quiet
用法举例:
例1、 获取当前/mnt/usb目录下cache占用量
[root@test nfs_dir] # mkdir /mnt/usb && mount /dev/msc /mnt/usb/[root@test usb] # vmtouch . Files: 57 Directories: 2 Resident Pages: 0/278786 0/1G 0% Elapsed: 0.023126 seconds例2、 当前test.bin文件的cache占用量?
[root@test usb] # vmtouch -v test.bintest.bin[ ] 0/25600Files: 1 Directories: 0 Resident Pages: 0/25600 0/100M 0% Elapsed: 0.001867 seconds 
这时使用tail命令将部分文件读取到内存中:
[root@test usb] # busybox_v400 tail -n 10 test.bin > /dev/null 
现在再来看一下:
[root@test usb] # vmtouch -v test.bintest.bin[ o] 240/25600Files: 1 Directories: 0 Resident Pages: 240/25600 960K/100M 0.938% Elapsed: 0.002019 seconds 可知目前文件test.bin的最后240个page驻留在内存中 。
 
例3、 最后使用-t选项将剩下的test.bin文件全部读入内存:
[root@test usb] # vmtouch -vt test.bintest.bin[OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO] 25600/25600Files: 1 Directories: 0 Touched Pages: 25600 (100M) Elapsed: 39.049 seconds 例4、 再把test.bin占用的cachae全部释放:
[root@test usb] # vmtouch -ev test.binEvicting test.binFiles: 1 Directories: 0 Evicted Pages: 25600 (100M) Elapsed: 0.01461 seconds这时候再来看下是否真的被释放了:
[root@test usb] # vmtouch -v test.bintest.bin[ ] 0/25600Files: 1 Directories: 0 Resident Pages: 0/25600 0/100M 0% Elapsed: 0.001867 seconds以上通过代码分析及实际操作总结了vmtouch工具的使用 , 建议APP组后续集成或借鉴vmtouch工具并灵活应用到后端设备中 , 必能达到有效管理和控制page cache的目的 。


推荐阅读