mmap(2)
のマニュアルページと検索結果から、mmap
は、システムの使用可能なアドレススペースからシステムの予約済みアドレススペースを差し引いたものに限られているという印象を受けました。したがって、32ビットのarmv7lでは、3GB =(4GB〜1GB)程度だと思います。私は実際にmmap
できたようなぜ32ビットのarmv7l上の4GBファイルが成功したのですか?
しかし、それは見えた問題なく5ギガバイトのファイル:
int main(int argc, char** argv) {
// stats
char * path = argv[1];
struct stat sb;
stat(path, &sb);
std::cout << "File size: " << sb.st_size << std::endl;
// open
int fd = open(path, O_RDONLY, S_IRWXU);
std::cout << "File descriptor: " << fd << std::endl;
int i;
for (i =0; i<10; ++i){
void *pa = mmap(
nullptr, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
std::cout << "PA: " << pa
<< ", MAP_FAILED: "
<< (pa == MAP_FAILED) << ", Status: "
<< strerror(errno) << std::endl;
}
}
-D_FILE_OFFSET_BITS=64
フラグ付きコンパイル:
g++ -D_FILE_OFFSET_BITS=64 test.cc
と結果利回り:
File size: 5045966585
File descriptor: 3
PA: 0x89f80000, MAP_FAILED: 0, Status: Success
PA: 0x5d34a000, MAP_FAILED: 0, Status: Success
PA: 0x30714000, MAP_FAILED: 0, Status: Success
PA: 0x3ade000, MAP_FAILED: 0, Status: Success
PA: 0xffffffff, MAP_FAILED: 1, Status: Cannot allocate memory
PA: 0xffffffff, MAP_FAILED: 1, Status: Cannot allocate memory
PA: 0xffffffff, MAP_FAILED: 1, Status: Cannot allocate memory
PA: 0xffffffff, MAP_FAILED: 1, Status: Cannot allocate memory
PA: 0xffffffff, MAP_FAILED: 1, Status: Cannot allocate memory
PA: 0xffffffff, MAP_FAILED: 1, Status: Cannot allocate memory
結果から、mmapは4回成功してからreal trouに入りましたベレス。しかし、ファイルが〜5GBなので、成功してはいけません。
私の質問は次のようになります。
- は
mmap
のために期待されるこの振る舞いですか? - もしそうでなければ、どこが間違っていましたか?
編集:それが利用可能である場合は、物理ADDRES拡張子で
(PAE)32ビットシステムは、2^32バイトよりもはるかにADDRESことができます。
PAEは無関係です
$> cat /proc/cpuinfo
Processor : ARMv7 Processor rev 4 (v7l)
processor : 0
BogoMIPS : 1436.46
processor : 1
BogoMIPS : 1436.46
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc07
CPU revision : 4
Hardware : sun7i
Revision : 0000
Serial : 09c11b9d52544848804857831651664b
あなたの質問とちょうど関係ないが、 'printf'書式' "%p" 'を使用してポインタを出力するときは、引数*は' void * 'でなければならないので、キャスティングは必要ありません。また、ポインタを出力するために 'void *'を取る[output operator overload](http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt)があるので、古いC 'printf '関数はまったく機能しません。 –
物理アドレス拡張(PAE)を使用すると、32ビットシステムでは2^32バイトを超えるアドレスを使用できます。 – hetepeperfan
'mmap()'の関数プロトタイプは何ですか? 2番目の引数が32ビットのみの場合、64ビットの 'sb.st_size'が切り捨てられている可能性があります。 –