MMAP(2) | FreeBSD System Calls Manual | MMAP(2) |
名称
mmap — メモリの割り付け、またはファイルまたはデバイスをメモリにマップするライブラリ
Standard C Library (libc, -lc)書式
#include < sys/mman.h> void *
mmap( void *addr, size_t len, int prot, int flags, int fd, off_t offset);
解説
mmap() システムコールによって、 addr から開始し、多くても len バイトが継続するページは、 fd によって記述されたオブジェクトからバイトオフセット offset で開始するようにマップされます。 len がページサイズの倍数でないなら、マップされた領域は、指定された範囲を越えて拡張されます。マップされたオブジェクトの終りを超えるそのような拡張は、0 で埋められます。addr が 0 でないなら、それは、システムへのヒントとして使用されます。 (システムの都合を考えて、領域の実際のアドレスは、指定されたアドレスと異なるかもしれません。) addr が 0 であるなら、アドレスは、システムによって選択されます。領域の実際の開始アドレスが返されます。成功した mmap は、割り付けられたアドレス範囲のあらゆる以前のマップを削除します。
保護 (領域のアクセスのしやすさ) は、次の値を論理和 ( or) することによって prot 引数で指定されます:
- PROT_NONE
- ページは、アクセスできません。
- PROT_READ
- ページは、読み込みできます。
- PROT_WRITE
- ページは、書み込みできます。
- PROT_EXEC
- ページは、実行できます。
flags 引数は、マップされたオブジェクトのタイプ、マッピングオプションとマップされたページのコピーに行なわれた修正が、プロセスに特有であるか、または他の参照と共有されることになっているかどうかを指定します。共有、マッピングタイプとオプションは、次の値を論理和 ( or) することによって flags 引数で指定されます:
- MAP_32BIT
- 現在のプロセスのアドレス空間の最初の 2GB の領域を要求します。適切な領域を見つけることができないんら、 mmap() は、失敗します。このフラグは、64 ビットのプラットフォームでのみ利用可能です。
- MAP_ALIGNED( n)
- 要求された境界で領域を整列します。適切な領域を見つけることができないなら、 mmap() は、失敗します。 n 引数は、希望の整列の 2 進数の対数を指定します。
- MAP_ALIGNED_SUPER
- 大きな (“スーパ”) ページの潜在的な使用を最大化する領域を整列します。適切な領域を見つけることができないなら、 mmap() は、失敗します。システムは、マップのサイズに基づいた適切なページサイズを選択します。領域の整列と同様に使用されたページサイズは、両方とも、マップされているファイルのプロパティによって影響されます。特に、ファイルの既存のページの物理アドレスは、特定の整列を要求します。領域は、あらゆる特定の境界で整列することは保証されません。
- MAP_ANON
- あらゆる特定のファイルに関連しなかった匿名のメモリをマップします。 MAP_ANON を作成のために使用されるファイル記述子は、-1 でなければなりません。 offset 引数は、0 でなければなりません。
- MAP_ANONYMOUS
- このフラグは、 MAP_ANON と同じであり、互換性のために提供されています。
- MAP_FIXED
- 指定したものとは異なっているアドレスを選択するシステムを許可しません。指定されたアドレスを使用することができないなら、 mmap() は、失敗します。 MAP_FIXED が指定されるなら、 addr は、ページサイズの倍数でなければなりません。 MAP_FIXED 要求が成功するなら、 mmap() によって確立されたマッピングは、 addr から addr + len までの範囲のプロセスのページのために以前のマッピングを置き換えます。このオプションの使用は、お勧めできません。
- MAP_HASSEMAPHORE
- 領域にセマフォが含まれている可能性があること、特殊な処理が必要な可能性があることをカーネルに通知します。
- MAP_INHERIT
- このフラグは、正式に公表されたものとして扱われたことはなく、もはやサポートされていません。さらなる情報は、 minherit(2) を参照してください。
- MAP_NOCORE
- 領域は、コアファイルに含まれません。
- MAP_NOSYNC
-
は、この VM マップを経由して汚されたデータを、無闇にではなく (通常は、ページャによって) 必要な時のみ物理的なメディアにフラッシュするようにします。普通、このオプションにより、更新デーモンは、このマップで汚されたページをフラッシュしないようになります。これにより、ファイルバックアップされた共有メモリのマッピングを使用して無関係なプロセスの間でメモリアクセスを効率的に共有することができるようになります。このオプションがないと、汚された VM ページは、頻繁 (通常 30-60 秒毎) にディスクにフラッシュされるかも知れず、そのような動作を必要としない場合 (例えば IPC のためにファイルを用いた共有 mmap 領域を用いている場合) パフォーマンスに問題が出ることがあります。
MAP_NOSYNC を使っているかにかかわらず、 VM/ ファイルシステムの一貫性は、保たれることに注意してください。このオプションは、
UNIX プラットフォーム間で (まだ) 移植性はありませんが、いくつかのプラットフォームでは、デフォルトで同じ動作をするように実装されているかも知れません。
警告! ftruncate(2) を使いファイルを拡張してから、つまりファイルに大きな穴を空けてから、その穴を共有 mmap() を修正して埋める場合、深刻なファイル断片化が生じる可能性があります。この断片化を避けるために、 mmap() でその領域を修正する前に、新規に拡張した領域に 0 を write() して、ファイルのバッキングストアを事前に割り当てておく必要があります。ディスクへのフラッシュが全くランダムに生じるため、断片化問題に特に敏感なのは、 MAP_NOSYNC ページです。
同じことが、 MAP_NOSYNC を使いファイルベースの共有メモリストアを実装する場合にも言えます。 ftruncate() してバッキングストアを作るのではなく、0 を write() してバッキングストアを作ることを推奨します。たとえば、“
dd if=filename of=/dev/null bs=32k
”を使うなどして巨大なファイルをシーケンシャルに読み込みながら、“iostat 1
”を呼び出すことで得られる KB/t (転送 1 回あたりのキロバイト数) を観察することでファイル断片化のテストが可能です。fsync(2) システムコールは、すべての汚染されたデータとファイルに関連づけられたメタデータ (NOSYNC の汚れた VM データを含む) を物理的媒体にフラッシュします。 sync(8) コマンドと sync(2) システムコールは、汚染された NOSYNC VM のデータを通常フラッシュしません。 BSD は、整合性のあるファイルシステムバッファキャッシュを実装したので、 msync(2) システムコールは、通常必要ではありません。しかしながら、それは、ファイルシステムバッファで汚い VM ページを関連させるために使用され、したがって、それらは、後でなくより早く物理的なメディアにフラッシュされます。
- MAP_PREFAULT_READ
- 領域中のあらゆるメモリ常駐のページが、読み込みアクセスのためにマップできるように、ページテーブルのような、呼び出しプロセスの最も低いレベルの仮想アドレス変換の構造を直ちに更新します。通常、これらの構造は、ゆっくり更新されます。このオプションの効果は、そうでなければ、その領域への初期の読み込みアクセスで起こる任意のソフトの誤りを除去することです。たとえ、このオプションが、 PROT_WRITE を含んで prot を排除しなくても、その領域への初期の書き込みアクセスでソフトの誤りを除去しません。
- MAP_PRIVATE
- 修正は、プロセス固有に行われます。
- MAP_SHARED
- 修正は、共有されます。
- MAP_STACK
- MAP_STACK は、 MAP_ANON および 0 の offset 指定を含みます。 fd 引数は、-1 でなければならず、 prot には少なくとも PROT_READ と PROT_WRITE が入っている必要があります。このオプションは、スタックの先頭を開始点とし下方に伸びる、サイズが最大で len バイトまで伸びるメモリ領域を作成します。スタックの先頭は、呼び出しから返された開始アドレスに len バイトを加えたものになります。最も伸びた場合のスタックの下端は、呼び出しによって返される開始アドレスになります。
close(2) システムコールは、ページをアンマップしません。詳細については、 munmap(2) を参照してください。
現在の設計では、プロセスは、スワップ空間の位置を指定できません。将来は、追加のマッピングタイプ MAP_SWAP を定義するかもしれません。この場合、ファイル記述子引数には、スワップを行うべきファイルまたはデバイスを指定します。
注
この実装は、 offset 引数で整列の制限を強制しませんが、移植性のあるプログラムは、ページで整列された値のみを使用しなければなりません。大きなページのマッピングは、オブジェクトに裏打ちされたページが、仮想アドレス空間と RAM の両方の一致するブロックで整列されることを必要とします。システムは、大きな物理ページの整列に一致する、仮想アドレス空間のマップの要求を整列させることによって RAM 中の大きなページによって既に裏打ちされているオブジェクトをマップするとき、大きなページのマップを使用することを自動的に試みます。システムは、RAM のページによってまだ裏打ちされない、オブジェクトの部分をマップするとき、さらに大きなページのマッピングを使用します。 MAP_ALIGNED_SUPER フラグは、マップが既存の大きなページと一致できるように、オブジェクトが既に大きなページを使用するなら、システムがこの整列を上書きすることを除いて、 MAP_ALIGNED に似ている大きなページのサイズへのマップの要求を整列する最適化です。このフラグは、まだ RAM に存在するページがないオブジェクトの最初のマップの大きなページの使用を最大化にするために主に役に立ちます。
戻り値
成功して終了すると、 mmap() は、マップされた領域へのポインタを返します。そうでなければ、 MAP_FAILED の値が返され、 errno は、エラーを示す値が設定されます。エラー
mmap() システムコールは、次の場合に失敗します:- [ EACCES]
- フラグ PROT_READ が prot 引数の一部として指定され、 fd が読み込みのためにオープンされていません。フラグ MAP_SHARED と PROT_WRITE が flags と prot 引数の一部として指定され、 fd が読み込みのためにオープンされていません。
- [ EBADF]
- fd 引数が有効なオープンされたファイルの記述子ではありません。
- [ EINVAL]
- MAP_FIXED が指定され、 addr 引数が整列されたページでない、または希望のアドレス空間の一部がユーザプロセスのための有効なアドレス空間の外にあります。
- [ EINVAL]
- MAP_FIXED と MAP_32BIT の両方が、指定され、求められるアドレス空間の一部が、ユーザアドレス空間の最初の 2GB の外側に存在します。
- [ EINVAL]
- len 引数が 0 と等しかった。
- [ EINVAL]
- MAP_ALIGNED が指定され、希望の整列が、マシンの仮想アドレスサイズより大きいか、またはページより小さかったのいずれかです。
- [ EINVAL]
- MAP_ANON が指定されて fd 引数が -1 ではありませんでした。
- [ EINVAL]
- MAP_ANON が指定され、 offset 引数が 0 ではありませんでした。
- [ ENODEV]
- MAP_ANON が、指定されていませんでした、そして fd は、通常またはキャラクタ特殊ファイルを参照していませんでした。
- [ ENOMEM]
- MAP_FIXED が指定され、 addr 引数が利用可能ではありませんでした。 MAP_ANON が指定され、利用可能なメモリが不足していました。
関連項目
madvise(2), mincore(2), minherit(2), mlock(2), mprotect(2), msync(2), munlock(2), munmap(2), getpagesize(3), getpagesizes(3)バグ
len 引数は、最大のファイルサイズまたは利用可能なユーザランドのアドレス空間に制限されています。システム制限とバグのために 32 ビットのシステムでは、1TB より大きなファイルを作ることはできませんが、アドレス空間は、より制限されています。 64 ビットのシステムでは、より大きいなファイルが利用可能です。以前に文書化されていた 2GB の制限は、文書のバグでした。その制限は、 FreeBSD 2.2 以降存在していません。
September 9, 2013 | FreeBSD |