madvise(2) メモリ利用に関するアドバイスを与える

書式

#include <sys/mman.h>

int madvise(void *addr, size_t length, int advice);

glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

madvise(): _BSD_SOURCE

説明

madvise() システムコールは、アドレス addr からはじまる length バイトのメモリブロックのページング入出力をどう扱えば良いか、 カーネルにアドバイスする。 これを用いると、 アプリケーションからカーネルに、 マップされたメモリや共有メモリをどのように扱ってほしいか伝えることができ、 カーネルはそれに応じて先読みやキャッシュなどの適切な手法を選択できる。 このコールはアプリケーションの動作そのものには影響しない (MADV_DONTNEED の場合は別) が、 性能には影響しうる。 なおこのアドバイスを受け入れるかどうかはカーネルに任される。

アドバイスは引き数 advice によって与える。以下のいずれかを指定できる。

MADV_NORMAL
特別な扱いは行わない。これがデフォルトである。
MADV_RANDOM
ページ参照はランダムな順序で行われそうだ。 (したがって、先読みはあまり効果がなさそうだ。)
MADV_SEQUENTIAL
ページ参照はシーケンシャルな順序で行われそうだ。 (したがって与えた範囲のページは積極的に先読みしておくと良いだろう。 またアクセスが終わったら速やかに解放して良い。)
MADV_WILLNEED
近い将来にアクセスされそうだ。 (したがってこれらのページを今のうちに先読みしておくといいだろう。)
MADV_DONTNEED
しばらくアクセスはなさそうだ。 (現時点でアプリケーションは与えた範囲の処理を終えている。 したがってカーネルはこれに関連するリソースを解放して良い。) これ以降この範囲のページへのアクセスがあると、 成功はするが、メモリの内容をマップ元のファイルからロードし直すことになる (mmap(2) を見よ) か、 または元ファイルがないマップページでは アクセスがあったときに 0 埋めが行われることになる。
MADV_REMOVE (Linux 2.6.16 以降)
指定された範囲のページと関連するバッキングストアを解放する。 現在のところ、 shmfs/tmpfs だけがこれに対応している。 他のファイルシステムでは ENOSYS が返される。
MADV_DONTFORK (Linux 2.6.16 以降)
fork(2) が行われた後、指定された範囲のページを子プロセスが利用できないようにする。 この機能は、書き込み時コピー (copy-on-write) 方式で、 fork(2) の後で親プロセスがページに書き込みを行った場合に ページの物理位置が変化しないようにするのに有効である (ページの再配置はハードウェアがそのページに DMA 転送を行うような場合に 問題を起こすことがある)。
MADV_DOFORK (Linux 2.6.16 以降)
MADV_DONTFORK の影響を取り消し、デフォルトの動作に戻す。 つまり、 fork(2) の前後でマッピングは継承されるようになる。
MADV_HWPOISON (Linux 2.6.32 以降)
ページに毒入れを行い、ハードウェアメモリの破損のようにそのページを取り扱う。 この操作は特権 (CAP_SYS_ADMIN を持った) プロセスだけが利用できる。 この操作の結果、呼び出したプロセスは SIGBUS を受け取り、そのページはアンマップされる。 この機能はメモリのエラー処理コードをテストするためのものである。 カーネルで CONFIG_MEMORY_FAILURE が有効になっている場合にのみ利用可能である。
MADV_SOFT_OFFLINE (Linux 2.6.33 以降)
addrlength で指定された範囲のページをソフトオフラインにする。 指定された範囲の各ページのメモリの内容は保持され (すなわち、次にアクセスされた際に、同じ内容が見えるが、新しい物理ページフレームになる)、 元のフレームはオフラインになる (すなわち、 そのフレームは使用される、通常のメモリ管理からは取り除かれる)。 MADV_SOFT_OFFLINE 操作の影響は呼び出したプロセスには見えない (つまり呼び出したプロセスの動作は変化しない)。 この機能はメモリのエラー処理コードをテストすることを目的に作られた。 カーネルで CONFIG_MEMORY_FAILURE が有効になっている場合にのみ利用可能である。
MADV_MERGEABLE (Linux 2.6.32 以降)
Kernel Samepage Merging (KSM; カーネルによる同じページの統合) を addrlength で指定された領域に対して有効にする。 カーネルは、 統合可能の印がついたユーザーメモリの領域を定期的にスキャンし、内容が全く同じページを探す。 内容が全く同じページがあれば、それらのページは書き込み保護 (write-protected) がかかった一つのページで置き換えられる (プロセスが後でページの内容を更新しようとした際には自動的にページのコピーが行われる)。 KSM はプライベートな無名ページ (anonymous pages) だけを統合する (mmap(2) 参照)。 KSM 機能は、 同じデータのインスタンスを大量に生成するアプリケーション (KVM などの仮想化システム) での利用を想定している。 この機能はプロセッシング能力を大量に消費する場合があり、注意して使用すること。 詳細は Linux カーネルソースファイル Documentation/vm/ksm.txt を参照。 MADV_MERGEABLEMADV_UNMERGEABLE は、 カーネルで CONFIG_KSM オプションを有効になっている場合にのみ利用できる。
MADV_UNMERGEABLE (Linux 2.6.32 以降)
指定されたアドレス範囲に関して、それ以前に行われた MADV_MERGEABLE 操作の効果を取り消す。 KSM は、 addrlength で指定されたアドレス範囲の統合済みのすべてのページの統合解除を行う。
MADV_HUGEPAGE (Linux 2.6.38 以降)
Transparent Huge Pages (THP) を addrlength で指定された領域に対して有効にする。 現在のところ、Transparent Huge Pages はプライベートな無名ページ (anonymous pages) についてのみ機能する。 カーネルは定期的にヒュージページ (huge page) 候補の印がついたページをスキャンし、ヒュージページと置き換える。 また、カーネルはその領域がヒュージページのサイズに合っている場合、ヒュージページを直接割り当てる (posix_memalign(2) 参照)。 この機能は、大きなデータマッピングを使用し、一度にそのメモリの大きな範囲にアクセスするようなアプリケーション (例えば QEMU のような仮想化システム) で使うことを主に想定されている。 この機能は非常に簡単にメモリを浪費してしまう (例えば、1 バイトしかアクセスしない 2MB のマッピングが、 4KB ページではなく 2MB の実際のメモリを使ってしまう)。 詳細は Linux カーネルソースファイル Documentation/vm/transhuge.txt を参照。 MADV_HUGEPAGEMADV_NOHUGEPAGE は、 カーネルで CONFIG_TRANSPARENT_HUGEPAGE オプションを有効になっている場合にのみ利用できる。
MADV_NOHUGEPAGE (Linux 2.6.38 以降)
addrlength で指定されたアドレス範囲のメモリがヒュージページに組み込まれないようにする。
MADV_DONTDUMP (Linux 3.4 以降)
コアダンプから addrlength で指定された範囲のページを除外する。 これは、 コアダンプに含めても役に立たないことが分かっている大きなメモリ領域があるアプリケーションで有用である。 MADV_DONTDUMP の効果は /proc/PID/coredump_filter ファイル経由で設定されたビットマスクよりも優先される (core(5) 参照)。
MADV_DODUMP (Linux 3.4 以降)
以前の MADV_DONTDUMP の効果を取り消す。

返り値

madvise() は成功すると 0 を返す。 エラーが起こると -1 を返し、 errno を適切な値に設定する。

エラー

EAGAIN
何らかのカーネルリソースが一時的に利用できなかった。
EBADF
指定したマップは存在するが、ファイルではないところをマップしている。
EINVAL
このエラーは以下の理由で発生する。
*
len が負の値である。
*
addr がページ境界ではない。
*
advice が有効な値でない。
*
アプリケーションがロックされたページや共有ページを (MADV_DONTNEED で) 解放 しようとしている。
*
adviceMADV_MERGEABLEMADV_UNMERGEABLE が指定されたが、 カーネルの設定が CONFIG_KSM が有効になっていなかった。
EIO
(MADV_WILLNEED の場合) この範囲のページングを行うと、 プロセスの RSS (resident set size) の最大値を越えてしまう。
ENOMEM
(MADV_WILLNEED の場合) メモリが足りず、ページングに失敗した。
ENOMEM
指定した範囲のアドレスが、現在マップされていない。 あるいはプロセスのアドレス空間の内部にない。

準拠

POSIX.1b. POSIX.1-2001 では、 posix_madvise(3) を POSIX_MADV_NORMAL, POSIX_MADV_RANDOM などの定数とともに記述していた (それぞれの振る舞いはここで述べたものに近い)。 ファイルアクセスに対しても posix_fadvise(2) という類似の関数が存在する。

MADV_REMOVE, MADV_DONTFORK, MADV_DOFORK, MADV_HWPOISON, MADV_MERGEABLE, MADV_UNMERGEABLE は Linux 固有である。

注意

Linux での注意

現在の Linux の実装 (2.4.0) では、 このシステムコールをアドバイスというよりは命令と見ている。 したがってこのアドバイスに対して通常行われる動作が不可能な場合は、 エラーを返すことがある (上記の エラー の記述を参照)。 この振舞いは標準とは異なる。

Linux の実装では addr のアドレスはページ境界の値でなければならない。また length は 0 であっても構わない。 また Linux 版の madvise() では、指定されたアドレス範囲にマップされていない部分があると、 これらを無視して残りの部分にアドバイスを適用する (しかしシステムコールに対してはちゃんと ENOMEM を返す)。

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。