Provided by: manpages-ja-dev_0.5.0.0.20210215+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/ に書かれている。