bionic (2) mmap.2.gz

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

名前

       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 引き数で指定される。

       addr が NULL の場合、カーネルがマッピングを作成するアドレスを選択する。  この方法は最も移植性のある新しい
       マッピングの作成方法である。  addr が NULL でない場合、カーネルはマッピングをどこに配置するかのヒントとし
       て addr を使用する。Linux では、マッピングはすぐ近くのページ境界に作成される。 新しいマッピングのアドレス
       は、呼び出しの返り値として返される。

       ファイルマッピングの内容は、  ファイルディスクリプター fd で参照されるファイル (もしくは他のオブジェクト)
       のオフセット offset から開始される length バイトのデータで初期化される  (ファイルマッピングは無名マッピン
       グの反対語である。  MAP_ANONYMOUS を参照)。 offsetsysconf(_SC_PAGE_SIZE) が返すページサイズの倍数でな
       ければならない。

       引き数 prot には、マッピングのメモリー保護をどのように行なうかを指定する  (ファイルのオープンモードと矛盾
       してはいけない)。  prot には、 PROT_NONE か、以下のフラグをひとつ以上ビット毎の論理和 (OR) をとったものを
       指定できる。

       PROT_EXEC  ページは実行可能である。

       PROT_READ  ページは読み込み可能である。

       PROT_WRITE ページに書き込み可能である。

       PROT_NONE  ページにはアクセスできない。

       flags  引き数により、マッピングに対する更新が同じ領域をマッピングしている  他のプロセスに見えるか、更新が
       マッピング元のファイルを通じて 伝えられるか、が決定される。この動作は、以下の値のいずれか一つだけ (複数は
       指定できない) を flags に含めることで指定する。

       MAP_SHARED このマッピングを共有する。  マッピングに対する更新はこのファイルをマッピングしている他のプロセ
                  ス から見える。更新はマッピング元のファイルを通じて伝えられる。 ただし、ファイルの実際の更新は
                  msync(2)  または munmap() が呼ばれるまで行われないこともある。

       MAP_PRIVATE
                  プライベートな copy-on-write (書き込み時コピー) マップを生成する。  マッピングに対する更新は同
                  じファイルをマッピングしている他のプロセス  には見えず、更新がマッピング元のファイルを通じて伝
                  えられることもない。 mmap()  の呼び出し後にマッピング元のファイルに対して行われた変更が、 マッ
                  プ領域に反映されるかどうかは規定されていない。

       上記の二つのフラグは POSIX.1-2001 で規定されている。

       さらに、以下の値のうち 0 個以上をビット毎の論理和 (OR) で flags に指定することができる。

       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 で初期化される。 引き数 fdoffset は無視される。 ただし、実装によっては MAP_ANONYMOUS (もしくは MAP_ANON)  が指定された場合、
              fd を -1  にする必要があり、  移植性が必要なアプリケーションでは必ず  fd  を  -1  にすべきである。
              MAP_ANONYMOUSMAP_SHARED を組み合わせての利用は カーネル 2.4 以降の Linux でのみサポートされて
              いる。

       MAP_DENYWRITE
              このフラグは無視される         (ずっと前は、マップ元のファイルへの書き込みを行おうとすると、エラー
              ETXTBUSY  で失敗するようにシグナルが設定されていたが、これは denial-of-service (サービス拒否) 攻撃
              の原因となった)。

       MAP_EXECUTABLE
              このフラグは無視される。

       MAP_FILE
              互換性のためのフラグ。無視される。

       MAP_FIXED
              addr をアドレスのヒントとして使用するのではなく、 addr  で指定されたアドレスをそのまま使用してマッ
              ピングを配置する。  addr はページサイズの倍数でなければならない。 addrlen で指定されたメモリー
              領域が既存のマッピングのページと重なる場合、 既存のマッピングの重なった部分は捨てられる。 もし指定
              されたアドレスが使用できない場合、 mmap()  は失敗する。 マッピングに対して固定アドレスを要求するの
              は移植性の面で劣るので、 このオプションは使用しないことを推奨する。

       MAP_GROWSDOWN
              スタック用に使用される。マッピングをメモリー内で逆向きに行うことを  カーネル仮想メモリーシステムに
              指示する。  (訳注:マッピングは通常はメモリーアドレスが増加する向きに行うが、 このオプションを指定
              すると逆向きにマッピングを行う)

       MAP_HUGETLB (Linux 2.6.32 以降)
              "huge       page"       を使ってマッピングを割り当てる。詳しい情報は、Linux       カーネルソースの
              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_POPULATEMAP_NONBLOCK  を
              組み合わせた場合の動作は実装し直されるかもしれない。

       MAP_NORESERVE
              このマッピングに対するスワップ空間の予約を行わない。  スワップ空間を予約した場合は、このマッピング
              の変更が必ず可能なことが 保証される。予約を行わなかった場合、物理メモリーに空きがないと 書き込み時
              に SIGSEGV エラーを受け取ることがある。 proc(5) の /proc/sys/vm/overcommit_memory ファイルについて
              の議論も参照。 バージョン 2.6 より前のカーネルでは、このフラグは書き込み可能な  プライベートマッピ
              ングについてのみ効果があった。

       MAP_POPULATE (Linux 2.5.46 以降)
              マッピング用のページテーブルを配置  (populate) する ファイルマッピングの場合には、これによりファイ
              ルが先読み (read-ahead) が行われる。この以後は、マッピングに対するアクセスがページフォールトで  ブ
              ロックされることがなくなる。 Linux 2.6.23 以降でのみプライベートマッピングについて MAP_POPULATE が
              サポートされている。

       MAP_STACK (Linux 2.6.27 以降)
              プロセスやスレッドのスタックに適したアドレスにマッピングを割り当てる。  現在のところ、このフラグは
              何もしないが、  glibc  のスレッド実装では使用されている。 これは、いくつかのアーキテクチャーではス
              タックの割り当てに関して特別な扱い が必要な場合に、glibc  にそのサポートを後で透過的に実装できるよ
              うにする ためである。

       MAP_UNINITIALIZED (Linux 2.6.33 以降)
              無名ページ  (anonymous page) のクリアを行わない。このフラグは組み込みデバイス での性能向上を目的に
              作られてものである。カーネルの設定で CONFIG_MMAP_ALLOW_UNINITIALIZED  オプションが有効になっている
              場合のみ、 このフラグは効果を持つ。 セキュリティ面の考慮から、このオプションは通常組み込みデバイス
              (すなわち、 ユーザーメモリーの内容を完全に制御化におけるデバイス) においてのみ有効にされる。

       上記のフラグの中では、 MAP_FIXED だけが POSIX.1-2001 で規定されている。  しかしながら、ほとんどのシステム
       で MAP_ANONYMOUS (またはその同義語である MAP_ANON)  もサポートされている。

       いくつかのシステムでは、上記以外にフラグとして  MAP_AUTOGROW, MAP_AUTORESRV, MAP_COPY, MAP_LOCAL が規定さ
       れている。

       mmap()  によってマップされたメモリーの属性は fork(2)  の際に継承される。

       ファイルはページサイズの整数倍の領域にマップされる。サイズがページサイズの       整数倍でないファイルの場
       合、マップ時に残りの領域は   0   で埋められ、この領域へ  書きこみを行ってもファイルに書き出されることはな
       い。マッピングを行った元 ファイルのサイズを変更した場合、元ファイルの追加されたり削除された領域に対応  す
       るマップされたページに対してどのような影響があるかは規定されていない。

   munmap()
       システムコール  munmap()  は指定されたアドレス範囲のマップを消去し、 これ以降のその範囲内へのメモリー参照
       は不正となる。 この領域は、プロセスが終了したときにも自動的にアンマップされる。  一方、ファイルディスクリ
       プターをクローズしても、この領域はアンマップされない。

       addr   アドレスはページサイズの整数倍でなければならない。指定された範囲の一部分を  含む全てのページはアン
       マップされ、これ以降にこれらのページへの参照があると  SIGSEGV  が発生する。  指定した範囲内にマップされた
       ページが一つも含まれていない場合でも エラーにならない。

   ファイルと関連付けられたマッピングに対するタイムスタンプの更新
       ファイルと関連付けられたマッピングの場合、マッピングされたファイルの st_atime フィールドは、 mmap()  され
       てからアンマップ (unmap) されるまでの間に更新されることがある。  それまでに更新が行われていなければ、マッ
       プされたページへの最初の参照があった 際に更新される。

       PROT_WRITEMAP_SHARED  の両方を指定してマップされたファイルの場合、書き込みがあると、  st_ctimest_mtime の両フィールドは、マップされた領域への書き込みより後で、 MS_SYNC または MS_ASYNC  フラグを指定し
       て msync(2)  が呼ばれる前までに更新される。

返り値

       mmap()   は成功するとマップされた領域へのポインターを返す。  失敗すると値 MAP_FAILED (つまり (void *) -1)
       を返し、 errno がエラーの内容にしたがってセットされる。 munmap()  は成功すると 0 を返す。失敗すると -1 を
       返し、 errno がセットされる (多くの場合 EINVAL になるだろう)。

エラー

       EACCES 以下のいずれかの場合。 ファイルディスクリプターの参照先が通常のファイルではない (non-regular file)
              。 ファイルマッピングを要求したが fd  は読み込み用にオープンされていない。  MAP_SHARED  を要求して
              PROT_WRITE をセットしたが fd は読み書きモード (O_RDWR)  でオープンされていない、 PROT_WRITE をセッ
              トしたが、ファイルは追加 (append) 専用である。

       EAGAIN ファイルがロックされている。またはロックされているメモリーが多すぎる (setrlimit(2)  を参照)。

       EBADF  fd が有効なファイルディスクリプター (file descriptor) ではない (かつ MAP_ANONYMOUS  がセットされて
              いない)。

       EINVAL addrlengthoffset が適切でない (例えば、大きすぎるとか、ページ境界にアラインメントされてい
              ない)。

       EINVAL (Linux 2.6.12 以降)  length が 0 であった。

       EINVAL flagsMAP_PRIVATEMAP_SHARED のどちらも含まれていなかった、もしくは その両方が含まれていた。

       ENFILE システム全体でオープンされているファイルの総数が上限に達した。

       ENODEV 指定されたファイルが置かれているファイルシステムがメモリーマッピングをサポート していない。

       ENOMEM メモリーに空きがない、または処理中のプロセスのマッピング数が最大数を超過した。

       EPERM  prot 引き数は PROT_EXEC を行うように指定されているが、 no-exec  でマウントされたファイルシステム上
              のファイルに マップ領域が対応している。

       EPERM  操作が file seal により禁止されている。 fcntl(2) 参照。

       ETXTBSY
              MAP_DENYWRITE がセットされているが fd で指定されているオブジェクトは書き込み用に開かれている。

       EOVERFLOW
              32  ビットアーキテクチャーで  large  file  拡張を使っている場合 (つまり 64 ビットの off_t を使う場
              合)、 length で使うページ数と offset で使うページ数を足した値は unsigned long (32 ビット) を超えて
              しまう (オーバーフローしてしまう) 場合がある。

       マップ領域を利用する際に、以下のシグナルが発生することがある:

       SIGSEGV
              読み込み専用で mmap された領域へ書き込みを行おうとした。

       SIGBUS バッファーのうち、ファイルに関連づけられていない部分 (例えばファイル末尾を越えた部分など。これには
              他のプロセスがファイルを切り詰めた場合なども含まれる)  にアクセスしようとした。

準拠

       SVr4, 4.4BSD, POSIX.1-2001.

可用性

       mmap(), msync(2)  munmap()  が利用可能な POSIX システムでは、 _POSIX_MAPPED_FILES は <unistd.h> で 0 より
       大きな値に定義される (sysconf(3) も参照のこと)。

注意

       (i386 などの) いくつかのアーキテクチャーでは、 PROT_WRITE をセットすると、暗黙のうちに PROT_READ がセット
       される。 PROT_READ をセットした際に暗黙のうちに PROT_EXEC  がセットされるかどうかは、アーキテクチャー依存
       である。  移植性を考慮したプログラムでは、 新規にマップした領域でコードを実行したい場合は、常に PROT_EXEC
       をセットすべきである。

       マッピングを作成する移植性のある方法は、 addr に 0 (NULL) を指定し、 flags から MAP_FIXED  を外すことであ
       る。  この場合、システムがマッピング用のアドレスの選択を行う。 アドレスは既存のマッピングと衝突しないよう
       に、 かつ 0 にならないように選択される。 MAP_FIXED  フラグが指定され、かつ  addr  が  0  (NULL)  の場合に
       は、マップされるアドレスが 0 (NULL) になる。

       特定の flags 定数は _BSD_SOURCE_SVID_SOURCE のいずれかが定義された場合にのみ定義される。 (_GNU_SOURCE
       も定義されている必要がある。これらのフラグはすべて Linux 固有のものなので、 特に _GNU_SOURCE を必要とする
       点はもっと論理的に決められるべきであった。)  関係するフラグは  MAP_32BIT,  MAP_ANONYMOUS  (とその同義語の
       MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK,
       MAP_NORESERVE, MAP_POPULATE, MAP_STACK である。

   C ライブラリとカーネル ABI の違い
       このページでは  glibc の mmap() のラッパー関数が提供するインターフェースに ついて説明している。元々は、こ
       の関数は同じ名前のシステムコールを起動していた。 カーネル 2.4 以降、このシステムコールは mmap2(2)  に取っ
       て代わられ、現在  では、  glibc  の mmap() のラッパー関数は offset を適切に調整してから mmap2(2) を起動す
       る。

バグ

       Linux においては、上記の MAP_NORESERVE で述べられているような保証はない。  デフォルトでは、システムがメモ
       リーを使い切った場合には、 どのプロセスがいつ強制終了されるか分からないからである。

       2.6.7 より前のカーネルでは、 protPROT_NONE が指定された場合にのみ、 MAP_POPULATE フラグが効力を持つ。

       SUSv3 では、 length が 0 の場合、 mmap()  は失敗すると規定されている。しかしながら、2.6.12 より前のカーネ
       ルでは、 この場合に mmap()   は成功していた  (マッピングは作成されず、  addr  が返されていた)。  カーネル
       2.6.12 以降では、 mmap()  はエラー EINVAL で失敗する。

       POSIX では、 システムはオブジェクト末尾の部分ページを常に 0 で埋め、 末尾より後ろのオブジェクトを決して変
       更してはならない、と規定している。 Linux では、  オブジェクト末尾より後ろの部分ページにデータを書き込んだ
       場合、  そのファイルをクローズしてアンマップした後であってもページキャッシュにデータが残り続け、 データが
       ファイル自体に書き込まれていなくても、 それ以降のマッピングで変更された内容が見える可能性がある。  いくつ
       かの場合では、 アンマップを行う前に msync(2) を呼び出すことで、 この状況を修正することができる。 しかし、
       これは tmpfs では機能しない (例えば、 shm_overview(7) で説明されている POSIX 共有メモリーインターフェース
       を使った場合)。

       以下のプログラムは、一番目のコマンドライン引き数で指定された  ファイルの一部を標準出力に表示する。 表示す
       る範囲は、二番目、三番目のコマンドライン引き数で渡される  オフセットと長さで指定される。   このプログラム
       は、指定されたファイルの必要なページのメモリー  マッピングを作成し、 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),  memfd_create(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)

       proc(5) の /proc/[pid]/maps, /proc/[pid]/map_files, /proc/[pid]/smaps の説明。

       B.O. Gallmeister, POSIX.4, O'Reilly, pp. 128-129 and 389-391.

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告
       に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。