32bitアプリで4GB以上のメモリ空間をアクセスする方法。
ARMなどの組込み系で、4GBを超えるメモリ空間にアクセスすることになったので備忘録。
ちなみに確認環境にRaspberry PIを使っているのは守秘義務のためw
pi@raspberrypi:~ $ uname -a Linux raspberrypi 4.14.114-v7+ #1 SMP Fri Jun 28 15:47:58 JST 2019 armv7l GNU/Linux
日本語のMan page of MMAPを参考に。
mmap()の第4引数 off_t が 32bitなのか64bitなのかが肝。
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
サンプルコードはこちら
実行結果
pi@raspberrypi:~ $ gcc m.c pi@raspberrypi:~ $ ./a.out sizeof(off_t) = 4 pi@raspberrypi:~ $ gcc m.c -D_FILE_OFFSET_BITS=64 pi@raspberrypi:~ $ ./a.out sizeof(off_t) = 8
コンパイラオプションに -D_FILE_OFFSET_BITS=64 を指定することで64bitアクセスが可能。
ちなみにソースコードの先頭行を下記のようにすることでも対応可能。
pi@raspberrypi:~ $ gcc m.c pi@raspberrypi:~ $ ./a.out sizeof(off_t) = 8
日本語のMan pageサイトは存在しない。
Debianのサイトmmap64(3) — manpages-ja-devを参考にするか、
Libcの本家のサイトmmap64(3) — Linux manual pageを参考にする。
ただ、第4引数が off_t だと32bitでは?と思い、ヘッダファイルを確認。
ファイルの所在は /usr/include/arm-linux-gnueabihf/sys/mman.h
ということで、__off64_t が実体らしい。
サンプルコードはこちら
実行結果
pi@raspberrypi:~ $ gcc m.c m.c: In function ‘main’: m.c:19:9: warning: implicit declaration of function ‘mmap64’ [-Wimplicit-function-declaration] addr = mmap64(NULL, 512, PROT_WRITE|PROT_READ, MAP_SHARED, fd, PHYSICAL_ADDR); ^~~~~~ m.c:19:7: warning: assignment makes pointer from integer without a cast [-Wint-conversion] addr = mmap64(NULL, 512, PROT_WRITE|PROT_READ, MAP_SHARED, fd, PHYSICAL_ADDR); ^ pi@raspberrypi:~ $ ./a.out sizeof(__off64_t) = 8
警告が出るので対応としては、コンパイルオプションに -D_LARGEFILE64_SOURCE=1 を指定する。
pi@raspberrypi:~ $ gcc m.c -D_LARGEFILE64_SOURCE=1 pi@raspberrypi:~ $ ./a.out sizeof(__off64_t) = 8
もしくはソースコードの先頭行を下記のようにすることでも対応可能。
pi@raspberrypi:~ $ gcc m.c pi@raspberrypi:~ $ ./a.out sizeof(__off64_t) = 8