2016-05-24 12 views
7

Miałem wrażenie ze strony man i wyników wyszukiwania, że ​​mmap ogranicza się tylko do dostępnych przestrzeni adresowych systemu, minus zarezerwowane przestrzenie adresowe systemu. Tak więc w przypadku 32-bitowego armv7l zakładam, że wynosi on około 3 GB = (4 GB - 1 GB).Dlaczego mmap plik 4GB na 32-bitowym armv7l powiodło się?

Ale wydawało się, że mogłem faktycznie mmap plikiem 5 GB bez problemu:

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

skompilować z -D_FILE_OFFSET_BITS=64 flag

g++ -D_FILE_OFFSET_BITS=64 test.cc 

a wydajności Wynik:

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 

Z wyników mmap udało się 4 razy, zanim wejdziemy w prawdziwe kłopoty bles. Ale nie powinno się to powieść, ponieważ plik ma ~ 5 GB.

Moje pytania to:

  1. Czy to zachowanie oczekuje na mmap?
  2. Jeśli nie, gdzie popełniłem błąd?

Edit:

Dzięki podczas wizyty fizycznego (PAE) rozszerzenia systemów 32-bitowych może podczas wizyty o wiele więcej niż 2^32 bajtów, jeśli jest dostępna.

Nie ma wsparcia dla tego procesora 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

Niezwiązane z twoim pytaniem i tylko dla FYI, ale podczas drukowania wskaźnika za pomocą 'printf' format' "% p" 'argument * powinien * być' void * ', więc nie trzeba rzucać. Ponadto występuje przeciążenie operatora wyjściowego (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) przy użyciu 'void *' używanego do drukowania wskaźników, więc nie ma potrzeby używania starego C 'printf 'funkcja w ogóle. –

+0

Dzięki fizycznym rozszerzeniom adresów (PAE) systemy 32-bitowe mogą adresować znacznie więcej niż 2^32 bajty, jeśli jest to możliwe. – hetepeperfan

+6

Co to jest prototyp funkcji dla 'mmap()'? Jeśli drugi argument ma tylko 32 bity, 64-bitowy plik 'sb.st_size' może zostać obcięty. –

Odpowiedz

6

PAE jest nieistotna. Nie chodzi o uzyskanie dostępu do dużej ilości pamięci fizycznej.

Problem polega na tym, że funkcja mmap przyjmuje 32-bitową wartość rozmiaru odwzorowania. Twój 64-bitowy rozmiar zostanie obcięty i faktycznie przydzielasz mniej niż 1 GB pamięci wirtualnej.

Powiązane problemy