2016-05-24 6 views
7

У меня создалось впечатление с man-страницы mmap(2) и результатами поиска, что mmap ограничен только адресным пространством системы, кроме системных зарезервированных адресных пространств. Так что на 32-битном armv7l я предполагаю, что он составляет около 3 ГБ = (4 ГБ - 1 ГБ).Почему файл mmap 4GB на 32-битном armv7l преуспел?

Но казалось, что я мог на самом деле mmap 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; 
     } 
} 

Compile с -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 раза, прежде чем отправиться в настоящую trou BLES. Но это не должно было преуспевать, так как файл ~ 5 ГБ.

Мои вопросы будут:

  1. Является ли это поведение ожидается mmap?
  2. Если нет, то где я сделал неправильно?

Edit:

С физической расширения (PAE Адресная) 32-битные системы могут значительно более Адресная чем 2^32 байт, если таковой имеется.

Там нет поддержки PAE для этого 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

Не связанный с вашим вопросом и только FYI, но при печати указателя с использованием формата 'printf'' '% p" 'аргумент * должен * быть' void * ', поэтому никакого кастинга не требуется. Также есть [перегрузка оператора вывода] (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) с использованием 'void *', используемого для печати указателей, поэтому нет необходимости в старом C 'printf 'функция вообще. –

+0

С дополнительными физическими расширениями addres (PAE) 32-разрядные системы могут добавлять гораздо больше, чем 2^32 байта, если это доступно. – hetepeperfan

+6

Что такое прототип функции для 'mmap()'? Если второй аргумент составляет всего 32 бита, ваш 64-разрядный 'sb.st_size' может быть усечен. –

ответ

6

PAE не имеет значения. Речь идет не о доступе к большим объемам физической памяти.

Проблема заключается в том, что ваша функция mmap принимает 32-битное значение для размера отображения. Таким образом, ваш 64-разрядный размер усекается, и вы фактически выделяете менее 1 ГБ виртуальной памяти.