2016-05-24 4 views
7

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なので、成功してはいけません。

私の質問は次のようになります。

  1. mmapのために期待されるこの振る舞いですか?
  2. もしそうでなければ、どこが間違っていましたか?

編集:それが利用可能である場合は、物理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 
+1

あなたの質問とちょうど関係ないが、 'printf'書式' "%p" 'を使用してポインタを出力するときは、引数*は' void * 'でなければならないので、キャスティングは必要ありません。また、ポインタを出力するために 'void *'を取る[output operator overload](http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt)があるので、古いC 'printf '関数はまったく機能しません。 –

+0

物理アドレス拡張(PAE)を使用すると、32ビットシステムでは2^32バイトを超えるアドレスを使用できます。 – hetepeperfan

+6

'mmap()'の関数プロトタイプは何ですか? 2番目の引数が32ビットのみの場合、64ビットの 'sb.st_size'が切り捨てられている可能性があります。 –

答えて

6

このCPUにはPAEのサポートはありません。これは、大量の物理メモリにアクセスすることではありません。

問題は、mmap関数がマッピングのサイズに対して32ビットの値をとることです。したがって、64ビットのサイズは切り捨てられ、実際には1 GB未満の仮想メモリを割り当てています。

関連する問題