mmapでMAP_FIXEDを利用する方法

mmapでMAP_FIXEDを利用する方法

Posted at November 4,2016 2:22 AM
Tag:[Linux]

mmapでMAP_FIXEDを利用する方法を紹介します。

1.はじめに

mmapはファイルの内容をメモリにマップするC/C++の関数です。

mmapの引数は、

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

となっています。各引数の意味は次のとおりです。

  • addr:新しいマッピングの開始アドレス
  • length:マッピングの長さ
  • prot:マッピングのメモリ保護
  • flags:マッピングに対する更新の見え方
  • offset:マッピング開始位置

manによるとmmapは次のような動作になります。

addr が NULL の場合、カーネルがマッピングを作成するアドレスを選択する。この方法は最も移植性のある新 しいマッピングの作成方法である。 addr が NULL でない場合、カーネルはマッピングをどこに配置するかのヒントとして addr を使用する。Linux では、マッピングはすぐ近くのページ境界に作成される。新しいマッピングのアドレスは、呼び出しの返り値として返される。(中略)ファイルマッピングの内容は、ファイルディスクリプタ fd で参照されるファイルのオフセット offset から開始される length バイトのデータで初期化される。

また、MAP_FIXEDはflagsに指定する値で、次のように定義されています。

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

つまり、引数addrで指定されたアドレスからマッピングできるようですが、非推奨のためかネットに情報がありません。

ということで、mmapでMAP_FIXEDを利用する方法を紹介します。

2.mmapでMAP_FIXEDを指定する

mmapでMAP_FIXEDを指定するには次のように実装すればいいようです。

#include <fstream>
#include <fcntl.h>
#include <sys/mman.h>
 
int main(int argc,char **argv) {
 
    // ファイルオープン
    int fd;
    fd = open(argv[1], O_RDONLY);
 
    // ファイルのマップ
    void* addr1 = mmap(0, 100, PROT_READ, MAP_SHARED, fd, 0);
    printf("mmap addr1:%p\n", addr1);
    if(addr1 == MAP_FAILED)
        perror("mmap NG");
    int result = munmap(addr1, 100);
    printf("munmap result:%d\n", result);
 
    // ファイルのマップ(MAP_FIXED)
    void* addr2 = mmap(addr1, 100, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0);
    printf("mmap addr2:%p\n", addr2);
    if(addr2 == MAP_FAILED)
        perror("mmap NG");
    result = munmap(addr2, 100);
    printf("munmap result:%d\n", result);
 
    return 1;
}

実行結果は次のとおりで、MAP_FIXEDを指定したmmapでは第1パラメータで指定したアドレスを取得できています。

[foo@hoge test]% ./a.out ./test.txt                                                                                   
mmap addr1:0x7f3ff4cbb000
munmap result:0
mmap addr2:0x7f3ff4cbb000
munmap result:0

ポイントは、MAP_SHAREDまたはMAP_PRIVATEを必ず指定することです。

  • MAP_SHARED:ファイルをマッピングしている他のプロセスから見える。
  • MAP_PRIVATE:プライベートな copy-on-write (書き込み時コピー) マップを生成する。

このいずれかとMAP_FIXEDをorで設定することで正常に動作します。

MAP_FIXED以外にもいくつかのフラグが用意されていますが、今回紹介した3つのフラグのみ、POSIX.1-2001(IEEE Std 1003.1-2001)で規定されています。

関連記事
トラックバックURL


コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)