mmapでMAP_FIXEDを利用する方法
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)で規定されています。
Posted by yujiro このページの先頭に戻る
- VMをundefineできない場合の対処
- cpanflute2でエラーになる場合の対処
- シェルスクリプトをバイナリ化する「shc」
- OpenSSLで文字列を暗号化・複号化する方法
- sshログインに時間がかかる場合の対処
- vi/vimで範囲指定して置換する方法
- vi/vimでマークした行に移動する方法
- vi/vimで複数行を一括削除する方法
- LinuxでOSキャッシュをクリアする方法
- lessで検索文字列だけを表示する方法
- tailコマンドでファイルがローテートされても追従する方法
- svnでファイルやディレクトリを削除する方法
- phpMyAdminで「unknown system variable 'lc_messages'」となる場合の対処
- Linux(CentOS)でapxsがみつからない場合の対処
- PHP7.3とApacheを連携させる方法
トラックバックURL
コメントする
greeting