mincore(2)でファイルがページキャッシュに乗っているか調べる
シェルから調べたい人
Google Code Archive - Long-term storage for Google Code Project Hosting.をインストールして、
fincore ファイル名
って打つ。
自分のプログラムから調べたい人
要するにさっきのfincoreコマンドから必要な所を抜き出してくれば良い。
以下はtest.datのキャッシュ中サイズを表示するプログラム。
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <sys/mman.h> #include <errno.h> long fincore(int fd, size_t length) { void *file_mmap; size_t page_index; size_t cached = 0; unsigned char *mincore_vec; size_t page_size = getpagesize(); size_t ret = -1; mincore_vec = calloc(1, (length+page_size-1)/page_size); if ( mincore_vec == NULL ) { perror( "Could not calloc" ); } file_mmap = mmap((void *)0, length, PROT_NONE, MAP_SHARED, fd, 0 ); if ( file_mmap == MAP_FAILED ) { perror( "mmap failed" ); goto cleanup; } if ( mincore(file_mmap, length, mincore_vec) != 0 ) { perror( "mincore" ); goto cleanup; } for (page_index = 0; page_index <= length/page_size; page_index++) if (mincore_vec[page_index]&1) ++cached; ret = (size_t)((long)cached * (long)page_size); cleanup: if ( file_mmap != MAP_FAILED ) munmap(file_mmap, length); if ( mincore_vec != NULL ) free(mincore_vec); return ret; } int main(void) { int fd; long cached; struct stat st; fd = open("test.dat", O_RDONLY); if (fd < 0) { perror("open"); return fd; } if (fstat(fd, &st)) { perror("fstat"); close(fd); return -1; } cached = fincore(fd, st.st_size); printf("%ld/%zd\n", cached, st.st_size); close(fd); return 0; }
詳細はMan page of MINCOREに書いてあるが、mincoreはあるページがページキャッシュに乗っているかを調べる関数なので、引数に渡すのはファイル名やfdじゃなくてメモリアドレスになっている。
まずファイルをmmapしてアドレスを得てからこれをmincoreに渡し、結果はmincore_vecに記録される。
mincore_vecはunsigned char[]で、ページごとにキャッシュ中かどうかを示すフラグが書き込まれる。
これを順に見ていけば、何ページキャッシュ済みか分かる。
POSIX標準じゃないようだけど、FreeBSD, NetBSD, OpenBSD, MacOS Xのmanには乗ってたので、どこでも大体同じように使えるんじゃないかな(※要検証