Mmap

 
mmap() は、UNIXのシステムコールのひとつで、ファイルやデバイスなどのオペレーティングシステム (OS) 上のリソースの一部または全部を連続した仮想アドレス空間にマッピングする関数である。
ファイルシステム上のリソースに対するアクセス方法として、ストリームI/Oを行うシステムコールとの比較で、ユーザ空間とカーネル空間の間で読み書きされるデータのブロック転送が多くのアーキテクチャ上では発生しないことから、好まれる場合がある。
デバイスでは、ioctl()とともにメモリマップドI/OやDMAなどの操作を抽象化するものとしてドライバからファイルI/Oサービスの一部として提供されることがある。
規格.
mmap()はPOSIXにより定義されており、POSIX準拠のOSで利用することができる。POSIXで定められた動作のほかに、各OS毎に独自の拡張が施されていることがよくあり、Linuxでも、mmap() はいくつかのOS固有のマッピングを生成可能である。
Win32 API の場合、対応する関数は、ファイルマッピングは CreateFileMapping() と MapViewOfFile()、無名マッピングは VirtualAlloc()。
ファイルマッピングと無名マッピング.
ファイルマッピング.
ファイルを仮想アドレス空間へマッピングした場合、OSはファイル上の対象となる領域のデータを、ビューとして、mmap()を呼び出したプロセスがアクセスできる仮想アドレス空間に割り当てる。そして、プロセスがマッピングされた領域へ書き込みを行った場合、MAP_SHARED を指定した場合は、OSはその変更を同期的あるいは非同期的にファイルへと反映する。MAP_SHARED と排他的な MAP_PRIVATE を指定した場合は、変更はファイルには反映されない。
無名マッピング.
ファイルの裏付けがないものを、無名 (Anonymous) マッピングと呼ぶ。無名マッピングを使用するには引数flags に MAP_ANONYMOUS を指定し、ファイルディスクリプタに -1 を指定する。無名マッピングを使うと利用可能なメモリ領域を仮想アドレス空間から確保できる。この機能は、アプリケーションの実行中にOSから追加のメモリリソースを獲得する方法として利用される。多くのUNIX系のCライブラリのmalloc()の実装は、小さなメモリ領域の確保はデータセグメントを拡張してそこから小分けに切り分け、大きなメモリ領域の確保のケースには mmap() を内部的に使っている。例えば、Doug Lea の実装した dlmalloc の場合、デフォルト値は256KB以上のメモリ確保に mmap() を使用する。
複数プロセス間におけるmmap.
複数のプロセスで、同じリソースの同じ領域をマッピングした場合の動作は、mmap()呼び出し時のパラメータや、OSの提供するマッピングのセマンティクスによって異なる。なお、MAP_SHARED, MAP_PRIVATE などのメモリの属性は、fork() により生じた子プロセスにおいても保持される。
MAP_SHARED.
MAP_SHARED を指定すると、マッピングされたメモリ領域が複数のプロセスで共有される。あるプロセスがマッピングされた領域に書き込んだ内容を、他のプロセスが（同期的あるいは非同期的に）即座に読むことができるようになる。この性質は、プロセス間通信の手法の1つとして（UNIX System Vの共有メモリ機構の代替として）使われることがある。
MAP_PRIVATE.
MAP_PRIVATE を指定すると、マッピングがコピーオンライトになる。そこでは、マッピングされたメモリ領域からの読み取りしか行われていない状況が続く限りプロセス間でマッピングが共有されるが、あるプロセスがメモリ領域に何かを書き込もうとした瞬間にオペレーティングシステムがマッピングを複製し、メモリ領域のコピーを生成したのち、その領域をプロセス固有のものとして位置づける。つまり、事実上、プロセス間ではマッピングが共有されていないということになり、この状況では、マッピングによるリソースへのアクセスは一貫性がないということになる。
アドレス指定.
通常は利用する仮想アドレス空間のアドレスは、mmap() 側が勝手に割り振るが、MAP_FIXED を指定した場合、もし、そこが空き領域であれば、好きなアドレスを利用できる。ただし、アドレス 0 だけは使用できない。また、アドレスはページサイズ（多くのケースで4KB）の倍数でないといけない。