名前
madvise -
メモリー利用に関するアドバイスを与える
書式
#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 以降)
- addr と length
で指定された範囲のページをソフトオフラインにする。
指定された範囲の各ページのメモリーの内容は保持され
(すなわち、次にアクセスされた際に、同じ内容が見えるが、新しい物理ページフレームになる)、
元のフレームはオフラインになる
(すなわち、
そのフレームは使用される、通常のメモリー管理からは取り除かれる)。
MADV_SOFT_OFFLINE
操作の影響は呼び出したプロセスには見えない
(つまり呼び出したプロセスの動作は変化しない)。
この機能はメモリーのエラー処理コードをテストすることを目的に作られた。
カーネルで CONFIG_MEMORY_FAILURE
が有効になっている場合にのみ利用可能である。
- MADV_MERGEABLE
(Linux 2.6.32 以降)
- Kernel Samepage Merging (KSM;
カーネルによる同じページの統合)
を addr と length
で指定された領域に対して有効にする。
カーネルは、
統合可能の印がついたユーザーメモリーの領域を定期的にスキャンし、内容が全く同じページを探す。
内容が全く同じページがあれば、それらのページは書き込み保護
(write-protected)
がかかった一つのページで置き換えられる
(プロセスが後でページの内容を更新しようとした際には自動的にページのコピーが行われる)。
KSM
はプライベートな無名ページ
(anonymous pages) だけを統合する
(mmap(2) 参照)。 KSM
機能は、
同じデータのインスタンスを大量に生成するアプリケーション
(KVM
などの仮想化システム)
での利用を想定している。
この機能はプロセッシング能力を大量に消費する場合があり、注意して使用すること。
詳細は Linux
カーネルソースファイル
Documentation/vm/ksm.txt を参照。
MADV_MERGEABLE と MADV_UNMERGEABLE は、
カーネルで CONFIG_KSM
オプションを有効になっている場合にのみ利用できる。
- MADV_UNMERGEABLE
(Linux 2.6.32 以降)
- 指定されたアドレス範囲に関して、それ以前に行われた
MADV_MERGEABLE
操作の効果を取り消す。
KSM は、 addr と length
で指定されたアドレス範囲の統合済みのすべてのページの統合解除を行う。
- MADV_HUGEPAGE
(Linux 2.6.38 以降)
- Transparent Huge Pages (THP) を addr と length
で指定された領域に対して有効にする。
現在のところ、Transparent Huge
Pages
はプライベートな無名ページ
(anonymous pages)
についてのみ機能する。
カーネルは定期的にヒュージページ
(huge page)
候補の印がついたページをスキャンし、ヒュージページと置き換える。
また、カーネルはその領域がヒュージページのサイズに合っている場合、ヒュージページを直接割り当てる
(posix_memalign(2) 参照)。
この機能は、大きなデータマッピングを使用し、一度にそのメモリーの大きな範囲にアクセスするようなアプリケーション
(例えば QEMU
のような仮想化システム)
で使うことを主に想定されている。
この機能は非常に簡単にメモリーを浪費してしまう
(例えば、1
バイトしかアクセスしない
2MB のマッピングが、 4KB
ページではなく 2MB
の実際のメモリーを使ってしまう)。
詳細は Linux
カーネルソースファイル
Documentation/vm/transhuge.txt を参照。
MADV_HUGEPAGE と MADV_NOHUGEPAGE は、
カーネルで
CONFIG_TRANSPARENT_HUGEPAGE
オプションを有効になっている場合にのみ利用できる。
- MADV_NOHUGEPAGE
(Linux 2.6.38 以降)
- addr と length
で指定されたアドレス範囲のメモリーがヒュージページに組み込まれないようにする。
- MADV_DONTDUMP
(Linux 3.4 以降)
- コアダンプから addr
と length
で指定された範囲のページを除外する。
これは、
コアダンプに含めても役に立たないことが分かっている大きなメモリー領域があるアプリケーションで有用である。
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 で) 解放
しようとしている。
- advice に MADV_MERGEABLE か
MADV_UNMERGEABLE
が指定されたが、
カーネルの設定が
CONFIG_KSM
が有効になっていなかった。
- EIO
- (MADV_WILLNEED の場合)
この範囲のページングを行うと、
プロセスの RSS (resident set size)
の最大値を越えてしまう。
- ENOMEM
- (MADV_WILLNEED の場合)
メモリーが足りず、ページングに失敗した。
- ENOMEM
- 指定した範囲のアドレスが、現在マップされていない。
あるいはプロセスのアドレス空間の内部にない。
バージョン
Linux 3.18
以降では、このシステムコールのサポートは任意となり、利用できるかはカーネルが
CONFIG_ADVISE_SYSCALLS
オプションを有効にしてコンパイルされているかに依存する。
準拠
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 の実装 (2.4.0)
では、
このシステムコールをアドバイスというよりは命令と見ている。
したがってこのアドバイスに対して通常行われる動作が不可能な場合は、
エラーを返すことがある
(上記の エラー
の記述を参照)。
この振舞いは標準とは異なる。
Linux の実装では addr
のアドレスはページ境界の値でなければならない。また
length は 0
であっても構わない。
また Linux 版の madvise()
では、指定されたアドレス範囲にマップされていない部分があると、
これらを無視して残りの部分にアドバイスを適用する
(しかしシステムコールに対してはちゃんと
ENOMEM を返す)。
関連項目
getrlimit(2), mincore(2), mmap(2),
mprotect(2), msync(2), munmap(2), prctl(2),
core(5)
この文書について
この man ページは Linux
man-pages
プロジェクトのリリース
3.79 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。