mremap(2) 仮想メモリ・アドレスを再マッピングする

書式

#define _GNU_SOURCE /* feature_test_macros(7) 参照 */
#include <sys/mman.h>


void *mremap(void *old_address, size_t old_size,
size_t new_size, int flags, ... /* void *new_address */);

説明

mremap() は既存のメモリ・マッピングの拡張 (または縮小) を行う。 同時に移動されることもある (flags 引き数と利用可能な仮想アドレス空間によって決まる)。

old_address は拡張 (または縮小) しようとする仮想メモリ・ブロック の元のアドレスである。old_address はページ境界に合っていなければ ならない点に注意すること。old_size は元の仮想メモリ・ブロックの サイズである。 new_size は要求する変更後の仮想メモリ・ブロックのサイズである。 5 番目の引き数として new_address を指定することができる。下記の MREMAP_FIXED の説明を参照のこと。

Linux ではメモリはページに分割される。ユーザー・プロセスは (一つまたは) 複数のリニアな仮想メモリセグメントを持つ。 それぞれの仮想メモリセグメントは一つ以上の実メモリ・ページ にマッピングされている (マッピング情報はページ・テーブルで管理される)。 仮想メモリセグメントにはセグメント毎の保護 (アクセス権) が設定されており、 メモリが不正にアクセスされた場合 (例えば読み込み専用のセグメントに 書き込んだ場合)、セグメンテーション侵害 (segmentation violation) を 引き起こす。また、セグメント外の仮想メモリにアクセスした場合にも セグメンテーション侵害が発生する。

mremap() は Linux のページ・テーブル方式を使用する。 mremap() は仮想アドレスとメモリ・ページのマッピングを変更する。これは非常に効率的な realloc(3) を実装するのに使用されている。

flags ビットマスク引数は 0 または以下のフラグを含む:

MREMAP_MAYMOVE
デフォルトでは、現在の位置にマッピングを拡張するための 十分な空きがなければ mremap() は失敗する。 このフラグが指定されると、カーネルは必要があればマッピングを 新しい仮想アドレスに再配置することができる マッピングが再配置されると、古いマッピング位置への絶対ポインタは 無効になる (マッピングの開始アドレスからの相対オフセットは有効のままである)。
MREMAP_FIXED (Linux 2.3.31 以降)
このフラグは mmap(2) の MAP_FIXED フラグと似たような目的で用いられる。 このフラグが指定されると、 mremap() は 5 番目の引き数 void *new_address を受け取り、この引数はマッピングが移動されるべきアドレスを指定する。 このアドレスはページ境界に合っていなければならない。 new_addressnew_size で指定されるアドレス範囲に過去のマッピングがあった場合、 そのマッピングはアンマップされる (unmapped)。 MREMAP_FIXED を指定した場合は、 MREMAP_MAYMOVE も指定しなければならない。

old_addressold_size で指定されるメモリセグメントが (mlock(2) や同様のもので) ロックされている場合、セグメントのサイズが変わったり 再配置されたりした時にロックも維持される。 その結果、プロセスによってロックされるメモリの量は変化する。

返り値

成功した場合は mremap() は新しい仮想メモリ領域へのポインタを返す。 エラーの場合は MAP_FAILED (すなわち (void *) -1) が返され、 errno が適切に設定される。

エラー

EAGAIN
呼び出し元がロックされているメモリセグメントを拡張しようとしたが、 RLIMIT_MEMLOCK リソース制限を越えずにこれを行うことができない。
EFAULT
「セグメンテーション違反(segmentation fault)」 old_address から old_address+old_size の 範囲のアドレスのどれかがこのプロセスにおいて不正な仮想メモリ・アドレスである。 たとえ要求したアドレス空間全体を含むようなマッピングがあったとしても、 それらのマッピングが異なった型ならば EFAULT を受け取るだろう。
EINVAL
不正な引き数が与えられた。 可能性のある原因は以下の通りである: たいていは old_address がページ境界に 合ってない; flagsMREMAP_MAYMOVE または MREMAP_FIXED 以外の値が指定されている; new_size がゼロ; new_size または new_address の値が不正; new_addressnew_size で指定される新しいアドレス範囲が old_addressold_size で指定される古いアドレス範囲と重なっている; MREMAP_FIXED が指定されているが MREMAP_MAYMOVE が指定されていない。
ENOMEM
現在の仮想アドレスではメモリ領域が拡張できず、 MREMAP_MAYMOVE フラグが flags に設定されていない。 または十分な (仮想) メモリが存在しない。

準拠

このコールは Linux 特有であり、移植を意図したプログラムで 使用すべきではない。

注意

バージョン 2.4 より前の glibc では、 MREMAP_FIXED の定義は公開されておらず、 mremap() のプロトタイプは new_address 引き数を取らなかった。

この文書について

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