pagemon でプロセスのメモリマッピングを覗き見る
pagemon というツールを知ったので、使い方を調べつつ何かしら学習ネタにできないかと考えた
smackerelofopinion.blogspot.jp
基本的な使い方
-p
で観察したいプロセスの pid を指定して起動する。特権が必要なので sudo なり root なりで実行するナリ。
sudo pagemon -p <pid>
するとプロセスの仮想アドレスと対応するページフレームの情報を取れる!
仮想アドレスとページフレームの詳細
指定した仮想アドレスとページフレームの詳細を表示できる (カーソルキーで移動可能) 。各項目の意味は OS の教科書を参照してね
メモリ使用量の統計を表示する
-v
で /proc/$pid/status
で取れるメモリの統計と、マイナーフォルト・メジャーフォルトの数値などを表示する
ページの中を覗き見る
Enter
で、バイナリエディタのように指定したページフレームの中身を見れる。この例では libc-2.17.so の先頭 1ページ分の中身を表示している。ELF
の文字が見えるね
リアルタイムでモニタ
一定の間隔で画面が更新されるので準リアルタイムにメモリマップの状態をモニタできるのが楽しい
例
次のGIFアニメは、無名ページを大量に確保して OOM Killer で SIGKILL されるプロセスを作ることで、 memory pressure が発生し、pagemon でモニタしているプロセスが mmap したファイルのページキャッシュが reclaim され、無名ページが swap out される様子を撮ったものだ
色の変化は次の挙動を示す
- 赤色が消える –> mmap(2) しているページキャッシュが reclaim された
- 黃色が緑になる –> ヒープの無名ページが swap out された
sar 等のツールで memory pressure がかかっている際の統計はとれるが、pagemon でページが剥ぎ取られるか視覚化されると違った角度からメモリサブシステムの挙動が理解できるよに思う
上の例で実行している $ oom
のソースは以下の通り
#include <stdio.h> #include <sys/time.h> #include <sys/resource.h> #include <stdlib.h> #include <unistd.h> #include <sys/time.h> int main() { struct timeval t; struct rusage usage; size_t pagesize = sysconf(_SC_PAGESIZE); size_t size = 1 * 512 * 1024; for (;;) { char *p = malloc(size); if (p == NULL) { perror("malloc"); exit(1); } for ( size_t i = 0; i < size; i += pagesize ) { p[i] = '@'; if ((gettimeofday(&t, NULL)) == -1) { perror("getrusage"); exit(1); } if ((getrusage(RUSAGE_SELF, &usage)) == -1) { perror("getrusage"); exit(1); } printf("[%d.%06d] RSS = %dKB\n", t.tv_sec, t.tv_usec, usage.ru_maxrss); } } }