mapped-check - mmapされているかを確認する

目的

ある領域がmmapされているか(アクセスしてもSEGVが起きないか)を、ユーザ空間からチェックしたい。
mincoreシステムコール(ある領域にDDRが割り当てられているかをチェックする)を使って実現できないか?

結果

mmapの有無は、以下のロジックで判定できる:

  1. mincore システムコールの戻り値が 0 → mmap されている
  2. 戻り値が -1 で errno=12(ENOMEM) → mmap されていない、もしくは munmap された

以下、詳細。

背景

mmapしてるはずの領域にアクセスしたプログラムが、SIGSEGVで死ぬ場合がある。
もしかしたら、誰か他の処理が munmap しているのかもしれない(競合問題?)。
アクセスする前に、ユーザ空間から、該当領域が mmap されているかを調べる方法が無いだろうか。

mincore システムコール

Linux には mincore(2) が用意されている。
これは、本来なら、仮想メモリ実メモリが割りあたっているかどうかを調べるもの:

mincore() は、呼び出し元プロセスの仮想メモリのページがコア (RAM) 内に存在し、ページ参照時にディスクアクセス (ページ・フォールト) を起こさないかどうかを示すベクトルを返す。

http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/mincore.2.html

ところが、「エラー」の節に以下の記述がある:

ENOMEM
addr から addr + length の間にマップされていないメモリがあった。

http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/mincore.2.html

つまり、mincore() が ENOMEM を返すかどうかで、mmap の有無がユーザ空間から判定できる?

実機で確認

mmap / munmap 状態を変えながら mincore を呼び出すプログラムを作成して、実行してみる。

trial-mincore.c
https://sssvn.jp/svn/spikelet/linux/mincore/trial-mincore.c

(ここでは、物理アドレスの 0x84000000 を 論理アドレスの 0x4400000 に map している)

実行結果:

---- unmapped ----
mincore(0x44000000) => -1, errno=12, vector[0]=0
---- mapped, not accessed ----
mincore(0x44000000) => 0, errno=0, vector[0]=1
---- mapped, accessed ----
mincore(0x44000000) => 0, errno=0, vector[0]=1
---- unmapped ----
mincore(0x44000000) => -1, errno=12, vector[0]=0

表にすると以下の通り:

map状況 mincore戻り値 errno
mmap済み 0 (不定)
mmapされていない -1 12

意図通りに、mmap の有無が、mincore の戻り値と errno で表現できている。