2016-05-24 23 views
7

mmap(2) man sayfasından ve arama sonuçlarından etkilendim, bu mmap sadece sistemin kullanılabilir adres alanları ile sınırlı, sistem ayrılmış adres alanları ile sınırlı. Yani 32 bit armv7l'de, 3GB = (4GB - 1GB) civarında olduğunu farz ediyorum. Aslında mmap could gibiNeden 32 bit armv7l'de bir 4GB dosya mmap başarılı oldu?

Ama görünüyordu sorunsuz bir 5 GB dosya:

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 bayrağıyla Derleme:

g++ -D_FILE_OFFSET_BITS=64 test.cc 

Ve sonuç verimleri:

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 

Sonuçlardan, mmap gerçek trou gitmeden önce 4 kez başarılı oldu bles. Ama dosya ~ 5GB olduğundan bu yana başarılı olmamalıydı.

Sorularım şöyle olacaktır:

  1. mmap için beklenen bu davranış mı?
  2. Değilse, nerede yanlış yaptım?

Düzenleme: Fiziksel addres uzantısı (PAE) 32 bit sistemlerde

can addres çok fazla 2^32 byte, o varsa.

bu CPU

$> 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

Sorunuzla ilgisi olmayan ve sadece FYI, ancak 'printf 'formatını kullanarak bir işaretçi yazdırırken"% p ", argüman * * bir * void * olmalıdır, bu yüzden döküm gerektirmez. Ayrıca bir [void *] işaretçisi basmak için kullanılan bir [çıkış operatör aşırı yükü] (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) vardır, bu yüzden eski C 'printf'e gerek yoktur 'işlev hiç. –

+0

Fiziksel eklenti uzantısı (PAE) ile 32-bit sistemler, mevcutsa 2^32 bayttan çok daha fazlasını ekleyebilir. – hetepeperfan

+6

mmap() 'işlevinin prototipi nedir? Eğer ikinci argüman sadece 32 bit ise, 64-bit 'sb.st_size' sizin kısaltılmış olabilir. –

cevap

6

PAE alakasız için PAE desteği yok. Bu büyük miktarlarda fiziksel belleğe erişmekle ilgili değil.

Sorun, mmap işlevinizin eşlemenin boyutu için 32 bitlik bir değer almasıdır. Dolayısıyla 64 bit boyutunuz kesiliyor ve aslında 1 GB'den daha az sanal bellek ayırıyorsunuz.