2016-05-24 14 views
7

Tôi đã có ấn tượng từ trang kết quả tìm kiếm và kết quả tìm kiếm mmap(2), rằng mmap chỉ giới hạn trong không gian địa chỉ có sẵn của hệ thống, trừ đi không gian địa chỉ dành riêng cho hệ thống. Vì vậy, trên armv7l 32-bit, tôi giả sử nó là khoảng 3GB = (4GB - 1GB).Tại sao mmap một tệp 4GB trên armv7l 32 bit đã thành công?

Nhưng dường như tôi có thể thực sự mmap một file 5 GB không có vấn đề:

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 với -D_FILE_OFFSET_BITS=64 cờ:

g++ -D_FILE_OFFSET_BITS=64 test.cc 

Và sản lượng kết quả:

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 

Từ kết quả, mmap đã thành công trong 4 lần trước khi đi vào nhóm thực bles. Nhưng nó không nên được thành công kể từ khi tập tin là ~ 5GB.

Câu hỏi của tôi sẽ là:

  1. là hành vi này dự kiến ​​cho mmap?
  2. Nếu không, tôi đã làm gì sai?

Edit:

Với phần mở rộng địa chỉ vật lý (PAE) hệ thống 32-bit có thể địa chỉ nhiều hơn 2^32 byte, nếu đó là có sẵn.

Không có hỗ trợ PAE cho CPU này

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

Không liên quan đến câu hỏi của bạn và chỉ FYI, nhưng khi in một con trỏ sử dụng định dạng 'printf'' "% p" 'đối số * nên * là' void * ', do đó không cần truyền. Ngoài ra còn có một [toán tử đầu ra quá tải] (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) lấy một 'void *' được sử dụng để in con trỏ, vì vậy không cần cho bản in C cũ của ' 'chức năng ở tất cả. –

+0

Với hệ thống 32-bit mở rộng vật lý (PAE) có thể thêm nhiều hơn 2^32 byte, nếu có. – hetepeperfan

+6

Nguyên mẫu hàm cho 'mmap()' là gì? Nếu đối số thứ hai chỉ là 32 bit, thì 'sb.st_size' 64 bit của bạn có thể bị cắt bớt. –

Trả lời

6

PAE là không thích hợp. Đây không phải là về việc truy cập một lượng lớn bộ nhớ vật lý.

Vấn đề là chức năng mmap của bạn có giá trị 32 bit cho kích thước của ánh xạ. Vì vậy, kích thước 64 bit của bạn bị cắt ngắn và bạn thực sự phân bổ ít hơn 1 GB bộ nhớ ảo.

Các vấn đề liên quan