Provided by: manpages-ja-dev_0.5.0.0.20161015+dfsg-1_all 

名前
mlock - メモリーのロックとロック解除を行う
書式
#include <sys/mman.h>
int mlock(const void *addr, size_t len);
int munlock(const void *addr, size_t len);
int mlockall(int flags);
int munlockall(void);
説明
mlock() と mlockall() はそれぞれ、呼び出し元プロセスの仮想アドレス空間の一部または全部を RAM 上にロック
し、メモリーがスワップエリアにページングされるのを防ぐ。 munlock() と munlockall() は逆の操作で、それぞ
れ呼び出し元プロセスの仮想アドレス空間の一部または全部を ロック解除する。つまり、指定された仮想アドレス範
囲のページは カーネルメモリーマネージャーから要求されればスワップアウトするようになる。 メモリーのロック
とロック解除はページ単位で行われる。
mlock() と munlock()
mlock() は addr から始まる長さ len バイトのアドレス範囲のページをロックする。 呼び出しが成功した場合に
は、 指定されたアドレス範囲を含む全てのページは RAM に残り続けることが保証される。 これらのページは後で
ロック解除されるまで RAM に残り続けることが保証される。
munlock() は、 addr から始まる長さ len バイトのアドレス範囲のページのロックを解除する。 この呼び出しを
行った後は、カーネルが、指定されたメモリー範囲を含む 全てのページを外部のスワップ空間に移動できるようにな
る。
mlockall() と munlockall()
mlockall() は呼び出し元プロセスのアドレス空間にマップされている全てのページを ロックする。これにはコー
ド、データ、スタックの 各セグメント、共有ライブラリ、カーネルのユーザー空間データ、 共有メモリー、メモ
リーマップされたファイルが含まれる。 システムコールが成功した場合には全てのマップされたページは RAM に 残
ることを保証される。 これらのページは後でロック解除されるまで RAM に残り続けることが保証される。
flags 引数は以下の内容の一つまたは複数のビット OR から構成される:
MCL_CURRENT 現在、プロセスのアドレス空間にマップされている全てのページをロックする。
MCL_FUTURE 将来、プロセスのアドレス空間にマップされる全てのページをロックする。 例えば、ヒープ (heap) や
スタックの成長により新しく必要になったページだけで なく、新しくメモリーマップされたファイルや
共有メモリー領域もロックされる。
MCL_FUTURE が指定されていると、以後のシステムコール (例えば、 mmap(2), sbrk(2), malloc(3)) は、ロックす
るバイト数が許可された最大値 (下記参照) を超えた場合に 失敗する可能性がある。 同様に、スタックの成長も失
敗する可能性がある。 その場合、カーネルはスタックの拡張を拒否し、 SIGSEGV をプロセスに送る。
munlockall() は、呼び出し元プロセスのアドレス空間にマッピングされている 全てのページをロック解除する。
返り値
成功した場合は、これらのシステムコールはゼロを返す。 エラーの場合は -1 が返され、 errno が適切に設定さ
れ、プロセスのアドレス空間におけるロックは変更されない。
エラー
ENOMEM (Linux 2.6.9 以降) 呼び出し元は非ゼロの ソフト資源制限 RLIMIT_MEMLOCK を持つが、制限が許可している
以上のメモリーをロックしようとした。 この制限は、プロセスが特権 (CAP_IPC_LOCK) を持っている場合は
適用されない。
ENOMEM (Linux 2.4 以前) 呼び出し元プロセスが RAM の半分以上をロックしようとした。
EPERM 呼び出し側が特権を持っていないが、 要求された操作を実行するには特権 (CAP_IPC_LOCK) が必要である。
mlock() と munlock() 用として:
EAGAIN 指定されたアドレス範囲の一部または全てをロックすることができなかった。
EINVAL start+len の加算の結果が start よりも小さかった (例えば、加算でオーバーフローが発生したなど)。
EINVAL (Linux ではこの意味で使われない) addr がページサイズの倍数ではない。
ENOMEM 指定されたアドレス範囲がプロセスのアドレス空間にマップされたページと 一致しない。
mlockall() 用として:
EINVAL 未知の flags が指定された。
munlockall() 用として:
EPERM (Linux 2.6.8 以前) 呼び出し元が権限 (CAP_IPC_LOCK) を持っていない。
準拠
POSIX.1-2001, SVr4.
可用性
mlock() と munlock() が使用可能な POSIX システムでは _POSIX_MEMLOCK_RANGE が <unistd.h> で定義されてい
る。 また、ページあたりのバイト数は、 <limits.h> で定義される定数 PAGESIZE から (定義されている場合)、も
しくは sysconf(_SC_PAGESIZE) を呼び出すことで決定できる。
mlockall() と munlockall() が利用可能な POSIX システムでは、 _POSIX_MEMLOCK は <unistd.h> で 0 より大き
い値に定義されている (sysconf(3) も参照のこと)。
注意
メモリーのロックの用途としては主に二つある: リアルタイム アルゴリズムと高いセキュリティの必要なデータ処理
である。リアルタイムの アプリケーションは決定的なタイミングやスケジューリングを必要とするが、 ページング
は予期しないプログラムの実行遅延をもたらす主要な要因となる。 リアルタイムのアプリケーションはたいていは
sched_setscheduler(2) でリアルタイムスケジューラに変更される。 暗号やセキュリティのソフトウェアはしばし
ばパスワードや秘密鍵のデータの ような重要なバイト列を扱う。ページングの結果、これらの秘密が スワップ用の
固定媒体に転送されるかもしれない。そして、セキュリティ ソフトウェアが RAM 上の秘密を削除して終了したずっ
と後になっても、 このスワップされたデータには敵がアクセスできる可能性がある (しかし、ラップトップといくつ
かのデスクトップコンピュータの サスペンドモードはシステムの RAM の内容をメモリーのロックに関わらず ディス
クに保存することに注意)。
リアルタイムプロセスが mlockall() を使ってページフォールトによる遅延を防ごうとする場合、 関数呼び出しに
よってページフォールトが発生しないように、 時間制限の厳しい部分 (time-critical section) に入る前に 十分な
量のロックされたスタックを確保しておく必要がある。 これを実現するには、十分な大きさの自動変数 (の配列) を
確保し、 これらのスタック用のページがメモリー上に確保されるようにこの配列に 書き込みを行う関数を用意
し、これを呼び出せばよい。こうすることで、 十分な量のページがスタックにマッピングされ、RAM にロックされ
る。 ダミーの書き込みを行うことによって、 時間制限の厳しい部分 (critical section) 内では書き込み時コピー
による ページフォールトさえも発生しないことが保証される。
メモリーロックは fork(2) で作成された子プロセスには継承されず、 execve(2) が呼ばれたり、プロセスが終了
した場合は 自動的に削除される (ロック解除される)。 mlockall() の MCL_FUTURE 設定は fork(2) で作成された子
プロセスには継承されず、 execve(2) の中でクリアされる。
あるアドレス範囲に対するメモリーロックは、そのアドレス範囲が munmap(2) によってアンマップされた場合は削
除される。
メモリーのロックは累積しない。 すなわち複数回 mlock() や mlockall() を呼び出してロックされたページで
も、 対応する範囲に対して munlock() を 1 回呼び出したり munlockall() を呼び出したりするだけでロック解除
される。 複数の場所や複数のプロセスにマップされているページは、少なくとも一つの場所、 一つのプロセスで
ロックされている限りは RAM に残り続ける。
Linux での注意
Linux では、 mlock() と munlock() は自動的に addr を端数切り捨てにより一番近いページ境界へと丸める。 し
かし POSIX.1-2001 は addr がページ境界に合っていることを要求する実装も許している。 そのため移植性を意図し
たアプリケーションではきちんと境界に合わせた方が良い。
Linux 固有の /proc/PID/status ファイルの VmLck フィールドには、 mlock(), mlockall() および mmap(2)
MAP_LOCKED を使って、 ID が PID のプロセスがロックしているメモリー量 (キロバイト単位) が 表示される。
制限と権限
Linux 2.6.8 以前では、メモリーをロックするためには特権 (CAP_IPC_LOCK) が必要で、 ソフト資源制限
RLIMIT_MEMLOCK はプロセスがどれだけのメモリーをロックできるかの制限を定義する。
Linux 2.6.9 以降では、特権を持つプロセスがロックできるメモリー量は無制限となり、 代わりにソフト資源制限
RLIMIT_MEMLOCK は特権を持たないプロセスがロックできるメモリー量の制限を定義する。
バグ
2.4.17 までの 2.4 シリーズの Linux カーネルには、 mlockall() MCL_FUTURE フラグが fork(2) で継承されると
言うバグがある。 これはカーネル 2.4.18 で修正された。
カーネル 2.6.9 以降では、特権を持ったプロセスが mlockall(MCL_FUTURE) を呼び出した後で、特権をなくした場合
(例えば、 実効 UID を 0 以外の値に変更するなどにより、 CAP_IPC_LOCK ケーパビリティを失った場合)、リソース
上限 RLIMIT_MEMLOCK に達すると、それ以降のメモリー割り当て (例えば mmap(2), brk(2)) は失敗する。
関連項目
mmap(2), setrlimit(2), shmctl(2), sysconf(3), proc(5), capabilities(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告
に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
Linux 2014-04-14 MLOCK(2)