other versions
other sections
MMAP(2) | Linux Programmer's Manual | MMAP(2) |
名前¶
mmap, munmap - ファイルやデバイスをメモリにマップ/アンマップする書式¶
#include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length);
説明¶
mmap() は、新しいマッピングを呼び出し元プロセスの仮想アドレス空間に作成する。 新しいマッピングの開始アドレスは addr で指定される。マッピングの長さは length 引き数で指定される。- PROT_EXEC
- ページは実行可能である。
- PROT_READ
- ページは読み込み可能である。
- PROT_WRITE
- ページに書き込み可能である。
- PROT_NONE
- ページにはアクセスできない。
- MAP_SHARED
- このマッピングを共有する。 マッピングに対する更新はこのファイルをマッピングしている他のプロセス から見える。更新はマッピング元のファイルを通じて伝えられる。 ただし、ファイルの実際の更新は msync(2) または munmap() が呼ばれるまで行われないこともある。
- MAP_PRIVATE
- プライベートな copy-on-write (書き込み時コピー) マップを生成する。 マッピングに対する更新は同じファイルをマッピングしている他のプロセス には見えず、更新がマッピング元のファイルを通じて伝えられることもない。 mmap() の呼び出し後にマッピング元のファイルに対して行われた変更が、 マップ領域に反映されるかどうかは規定されていない。
- MAP_32BIT (Linux 2.4.20, 2.6 以降)
- マッピングをプロセスのアドレス空間の先頭 2 ギガバイト以内に配置する。 このフラグがサポートされているのは x86-64 アーキテクチャ上の 64 ビットプログラムのみである。 このフラグが追加されたのは、スレッドのスタックをメモリの先頭 2GB 以内の どこかに割り当てることで、初期のいくつかの 64 ビットプロセッサにおける コンテキストスイッチの性能問題を改善するためである。 最近の x86-64 プロセッサではこの性能問題はもはや存在せず、 そのようなシステムではこのフラグを使用する必要はない。 MAP_FIXED がセットされている場合は、 MAP_32BIT フラグは無視される。
- MAP_ANON
- MAP_ANONYMOUS の同義語。非推奨。
- MAP_ANONYMOUS
- マッピングはどのファイルとも関連付けされない。 マッピングの内容は 0 で初期化される。 引き数 fd と offset は無視される。 ただし、実装によっては MAP_ANONYMOUS (もしくは MAP_ANON) が指定された場合、 fd を -1 にする必要があり、 移植性が必要なアプリケーションでは必ず fd を -1 にすべきである。 MAP_ANONYMOUS と MAP_SHARED を組み合わせての利用は カーネル 2.4 以降の Linux でのみサポートされている。
- MAP_DENYWRITE
- このフラグは無視される (ずっと前は、マップ元のファイルへの書き込みを行おうとすると、エラー ETXTBUSY で失敗するようにシグナルが設定されていたが、これは denial-of-service (サービス拒否) 攻撃の原因となった)。
- MAP_EXECUTABLE
- このフラグは無視される。
- MAP_FILE
- 互換性のためのフラグ。無視される。
- MAP_FIXED
- addr をアドレスのヒントとして使用するのではなく、 addr で指定されたアドレスをそのまま使用してマッピングを配置する。 addr はページサイズの倍数でなければならない。 addr と len で指定されたメモリ領域が既存のマッピングのページと重なる場合、 既存のマッピングの重なった部分は捨てられる。 もし指定されたアドレスが使用できない場合、 mmap() は失敗する。 マッピングに対して固定アドレスを要求するのは移植性の面で劣るので、 このオプションは使用しないことを推奨する。
- MAP_GROWSDOWN
- スタック用に使用される。マッピングをメモリ内で逆向きに行うことを カーネル仮想メモリシステムに指示する。 (訳注:マッピングは通常はメモリ・アドレスが増加する向きに行うが、 このオプションを指定すると逆向きにマッピングを行う)
- MAP_HUGETLB (Linux 2.6.32 以降)
- "huge page" を使ってマッピングを割り当てる。 詳しい情報は、カーネル・ソースの Documentation/vm/hugetlbpage.txt を参照。
- MAP_LOCKED (Linux 2.5.37 以降)
- マップされた領域のページを mlock(2) の方法でメモリ内にロックする。 それ以前のカーネルでは、このフラグは無視される。
- MAP_NONBLOCK (Linux 2.5.46 以降)
- MAP_POPULATE と組み合わせた場合のみ意味を持つ。 read-ahead (前もって読み込むこと) を実行しない。 単に、すでに RAM 上に存在するページに対して ページテーブルエントリを作成するだけである。 Linux 2.6.23 以降では、このフラグは MAP_POPULATE に何の影響も与えない。 いつか MAP_POPULATE と MAP_NONBLOCK を組み合わせた場合の動作は実装し直されるかもしれない。
- MAP_NORESERVE
- このマッピングに対するスワップ空間の予約を行わない。 スワップ空間を予約した場合は、このマッピングの変更が必ず可能なことが 保証される。予約を行わなかった場合、物理メモリに空きがないと 書き込み時に SIGSEGV エラーを受け取ることがある。 proc(5) の /proc/sys/vm/overcommit_memory ファイルについての議論も参照。 バージョン 2.6 より前のカーネルでは、このフラグは書き込み可能な プライベート・マッピングについてのみ効果があった。
- MAP_POPULATE (Linux 2.5.46 以降)
- マッピング用のページテーブルを配置 (populate) する ファイルマッピングの場合には、これによりファイルが先読み (read-ahead) が行われる。この以後は、マッピングに対するアクセスがページフォールトで ブロックされることがなくなる。 MAP_POPULATE は Linux 2.6.23 以降でプライベート・マッピングについてのみ サポートされている。
- MAP_STACK (Linux 2.6.27 以降)
- プロセスやスレッドのスタックに適したアドレスにマッピングを割り当てる。 現在のところ、このフラグは何もしないが、 glibc のスレッド実装では使用されている。 これは、いくつかのアーキテクチャではスタックの割り当てに関して特別な扱い が必要な場合に、glibc にそのサポートを後で透過的に実装できるようにする ためである。
- MAP_UNINITIALIZED (Linux 2.6.33 以降)
- 無名ページ (anonymous page) のクリアを行わない。このフラグは組み込みデバイス での性能向上を目的に作られてものである。カーネルの設定で CONFIG_MMAP_ALLOW_UNINITIALIZED オプションが有効になっている場合のみ、 このフラグは効果を持つ。 セキュリティ面の考慮から、このオプションは通常組み込みデバイス (すなわち、 ユーザメモリの内容を完全に制御化におけるデバイス) においてのみ有効にされる。
munmap()¶
システムコール munmap() は指定されたアドレス範囲のマップを消去し、 これ以降のその範囲内へのメモリ参照は不正となる。 この領域は、プロセスが終了したときにも自動的にアンマップされる。 一方、ファイル記述子をクローズしても、この領域はアンマップされない。 addr アドレスはページサイズの整数倍でなければならない。指定された範囲の一部分を 含む全てのページはアンマップされ、これ以降にこれらのページへの参照があると SIGSEGV が発生する。 指定した範囲内にマップされたページが一つも含まれていない場合でも エラーにならない。ファイルと関連付けられたマッピングに対するタイムスタンプの更新¶
ファイルと関連付けられたマッピングの場合、マッピングされたファイルの st_atime フィールドは、 mmap() されてからアンマップ (unmap) されるまでの間に更新されることがある。 それまでに更新が行われていなければ、マップされたページへの最初の参照があった 際に更新される。 PROT_WRITE と MAP_SHARED の両方を指定してマップされたファイルの場合、書き込みがあると、 st_ctime と st_mtime の両フィールドは、マップされた領域への書き込みより後で、 MS_SYNC または MS_ASYNC フラグを指定して msync(2) が呼ばれる前までに更新される。返り値¶
mmap() は成功するとマップされた領域へのポインタを返す。 失敗すると値 MAP_FAILED (つまり (void *) -1) を返し、 errno がエラーの内容にしたがってセットされる。 munmap() は成功すると 0 を返す。失敗すると -1 を返し、 errno がセットされる (多くの場合 EINVAL になるだろう)。エラー¶
- EACCES
- 以下のいずれかの場合。 ファイル記述子の参照先が通常のファイルではない (non-regular file) 。 MAP_PRIVATE を要求したが fd は読み込み用にオープンされていない。 MAP_SHARED を要求して PROT_WRITE をセットしたが fd は読み書きモード ( O_RDWR) でオープンされていない、 PROT_WRITE をセットしたが、ファイルは追加 (append) 専用である。
- EAGAIN
- ファイルがロックされている。またはロックされているメモリが多すぎる ( setrlimit(2) を参照)。
- EBADF
- fd が有効なファイル記述子 (file descriptor) ではない (かつ MAP_ANONYMOUS がセットされていない)。
- EINVAL
- addr か length か offset が適切でない (例えば、大きすぎるとか、ページ境界にアラインメントされていない)。
- EINVAL
- (Linux 2.6.12 以降) length が 0 であった。
- EINVAL
- flags に MAP_PRIVATE と MAP_SHARED のどちらも含まれていなかった、もしくは その両方が含まれていた。
- ENFILE
- システム全体でオープンされているファイルの総数が上限に達した。
- ENODEV
- 指定されたファイルが置かれているファイルシステムがメモリマッピングをサポート していない。
- ENOMEM
- メモリに空きがない、または処理中のプロセスのマッピング数が最大数を超過した。
- EPERM
- prot 引き数は PROT_EXEC を行うように指定されているが、 no-exec でマウントされたファイルシステム上のファイルに マップ領域が対応している。
- ETXTBSY
- MAP_DENYWRITE がセットされているが fd で指定されているオブジェクトは書き込み用に開かれている。
- SIGSEGV
- 読み込み専用で mmap された領域へ書き込みを行おうとした。
- SIGBUS
- バッファのうち、ファイルに関連づけられていない部分 (例えばファイル末尾を越えた部分など。これには 他のプロセスがファイルを切り詰めた場合なども含まれる) にアクセスしようとした。
準拠¶
SVr4, 4.4BSD, POSIX.1-2001.可用性¶
mmap(), msync(2) munmap() が利用可能な POSIX システムでは、 _POSIX_MAPPED_FILES は <unistd.h> で 0 より大きな値に定義される ( sysconf(3) も参照のこと)。注意¶
このページでは glibc の mmap() のラッパー関数が提供するインターフェースに ついて説明している。元々は、この関数は同じ名前のシステムコールを起動していた。 カーネル 2.4 以降、このシステムコールは mmap2(2) に取って代わられ、現在 では、 glibc の mmap() のラッパー関数は offset を適切に調整してから mmap2(2) を起動する。バグ¶
Linux においては、上記の MAP_NORESERVE で述べられているような保証はない。 デフォルトでは、システムがメモリを使い切った場合には、 どのプロセスがいつ強制終了されるか分からないからである。例¶
以下のプログラムは、一番目のコマンドライン引き数で指定された ファイルの一部を標準出力に表示する。 表示する範囲は、二番目、三番目のコマンドライン引き数で渡される オフセットと長さで指定される。 このプログラムは、指定されたファイルの必要なページのメモリ・ マッピングを作成し、 write(2) を使って所望のバイトを出力する。#include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { char *addr; int fd; struct stat sb; off_t offset, pa_offset; size_t length; ssize_t s; if (argc < 3 || argc > 4) { fprintf(stderr, "%s file offset [length]\n", argv[0]); exit(EXIT_FAILURE); } fd = open(argv[1], O_RDONLY); if (fd == -1) handle_error("open"); if (fstat(fd, &sb) == -1) /* To obtain file size */ handle_error("fstat"); offset = atoi(argv[2]); pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1); /* offset for mmap() must be page aligned */ if (offset >= sb.st_size) { fprintf(stderr, "offset is past end of file\n"); exit(EXIT_FAILURE); } if (argc == 4) { length = atoi(argv[3]); if (offset + length > sb.st_size) length = sb.st_size - offset; /* Can't display bytes past end of file */ } else { /* No length arg ==> display to end of file */ length = sb.st_size - offset; } addr = mmap(NULL, length + offset - pa_offset, PROT_READ, MAP_PRIVATE, fd, pa_offset); if (addr == MAP_FAILED) handle_error("mmap"); s = write(STDOUT_FILENO, addr + offset - pa_offset, length); if (s != length) { if (s == -1) handle_error("write"); fprintf(stderr, "partial write"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
関連項目¶
getpagesize(2), mincore(2), mlock(2), mmap2(2), mprotect(2), mremap(2), msync(2), remap_file_pages(2), setrlimit(2), shmat(2), shm_open(3), shm_overview(7)この文書について¶
この man ページは Linux man-pages プロジェクトのリリース 3.41 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-04-16 | Linux |