2016-05-24 26 views
7

Ho avuto l'impressione dalla pagina man mmap(2) e risultati di ricerca, che mmap è limitato solo agli spazi di indirizzi disponibili del sistema, meno gli spazi degli indirizzi riservati del sistema. Quindi su armv7l a 32 bit, presumo che sia intorno a 3 GB = (4 GB - 1 GB).Perché mmap un file da 4 GB su armv7l a 32 bit è riuscito?

ma sembrava che ho potuto effettivamente mmap un file di 5 GB senza alcun problema:

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; 
     } 
} 

Compila con -D_FILE_OFFSET_BITS=64 bandiera:

g++ -D_FILE_OFFSET_BITS=64 test.cc 

E i rendimenti dei risultati:

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 

Dai risultati, mmap è riuscito per 4 volte prima di entrare in vero trou bles. Ma non dovrebbe essere successo poiché il file è ~ 5 GB.

Le mie domande sarebbero:

  1. È questo il comportamento previsto per mmap?
  2. In caso contrario, dove ho sbagliato?

Edit:

Con estensione addres fisico (PAE) sistemi a 32 bit può Addres molto più di 2^32 byte, se è disponibile.

Non c'è alcun supporto PAE per questa 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

Non correlato alla tua domanda e solo FYI, ma quando si stampa un puntatore utilizzando il 'printf' format' "% p" 'l'argomento * dovrebbe * essere un' void * ', quindi non è necessario il cast. Inoltre c'è un [overload dell'operatore di output] (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) che utilizza un 'void *' per stampare i puntatori, quindi non c'è bisogno del vecchio C 'printf 'funzione a tutti. –

+0

Con estensione fisica addres (PAE) i sistemi a 32 bit possono aggiungere molto più di 2^32 byte, se disponibile. – hetepeperfan

+6

Qual è il prototipo di funzione per 'mmap()'? Se il secondo argomento è solo a 32 bit, il tuo 'sb.st_size' a 64 bit potrebbe essere troncato. –

risposta

6

PAE è irrilevante. Non si tratta di accedere a grandi quantità di memoria fisica.

Il problema è che la funzione mmap assume un valore a 32 bit per la dimensione della mappatura. Quindi le dimensioni a 64 bit vengono troncate e in realtà stai allocando meno di 1 GB di memoria virtuale.