2016-08-13 44 views
0

我正在嘗試編寫一個程序,在該程序中分配一塊內存,然後有選擇地更改該塊的頁面大小和頁面對齊子集的保護。但是,當我嘗試在內存塊的大於8頁的部分內存中調用mprotect時,mprotect將失敗,並顯示錯誤「無法分配內存」。mprotect在撥打一定數量的電話後失敗

這裏是能重現問題最小,完整的,並且覈查例如:

#include <sys/mman.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <cerrno> 
#include <cstring> 
#include <iostream> 

int main() { 
    const int n_pages = 12; 
    const int page_size = sysconf(_SC_PAGE_SIZE); // 4096 
    const int block_size = n_pages * page_size;  // 65536 

    char* block_addr = (char*)aligned_alloc(page_size, block_size); 
    char* chunks[n_pages]; 
    char* pointer = block_addr; 

    for (int n = 0; n < n_pages; n++) { 
     pointer = pointer + (n * page_size); 
     chunks[n] = pointer; 
    } 
    std::cout << "Set chunks read-only.\n"; 
    for (int n = 0; n < n_pages; n++) { 
     if (mprotect(chunks[n], page_size, PROT_READ) != 0) { 
      std::cerr << n+1 << '/' << n_pages << ' ' 
         << "mprotect failed: " << std::strerror(errno) << '\n'; 
     } 
    } 
    std::cout << "Set chunks read/write.\n"; 
    for (int n = 0; n < n_pages; n++) { 
     if (mprotect(chunks[n], page_size, PROT_READ|PROT_WRITE) != 0) { 
      std::cerr << n+1 << '/' << n_pages << ' ' 
         << "mprotect failed: " << std::strerror(errno) << '\n'; 
     } 
    } 
    free(block_addr); 
} 

這始終未能對組塊N> 8,給出以下消息:

Set chunks read-only. 
9/12 mprotect failed: Cannot allocate memory 
10/12 mprotect failed: Cannot allocate memory 
11/12 mprotect failed: Cannot allocate memory 
12/12 mprotect failed: Cannot allocate memory 
Set chunks read/write. 
9/12 mprotect failed: Cannot allocate memory 
10/12 mprotect failed: Cannot allocate memory 
11/12 mprotect failed: Cannot allocate memory 
12/12 mprotect failed: Cannot allocate memory 

我發現了一個question其中OP似乎得到了與我相同的錯誤,其中David Hammen有用地提供了一些提示問題的根源,但我並不真正瞭解他在說什麼。不幸的是,OP沒有提供他們的代碼,所以我們無法確切知道他們在做什麼或者他們如何修復它。

所以基本上我的問題是:爲什麼mprotect會產生這個錯誤,我該如何解決?

+0

「*我真的不明白他在說什麼*」 - 究竟是什麼不清楚? – melpomene

+0

問題是'ENOMEM'(你得到的錯誤)可能意味着三件不同的事情,並且知道它是什麼意思並不總是容易的。您是否閱讀過[mprotect'手冊頁]中的說明(http://man7.org/linux/man-pages/man2/mprotect.2.html)?你可以消除一個或最好兩個在那裏的情況? –

+0

@melpomene我不明白他的意思是確保頁面已被映射,我的意思是頁面是或不被映射:) –

回答

2
pointer = pointer + (n * page_size); 

這條線看起來非常可疑。它可能應該是

pointer = block_addr + (n * page_size); 

chunks[n] = pointer; // need to assign to chunks[n] first 
    pointer = pointer + page_size; 

否則pointer將走離(在0,1(= 0 + 1),3(= 0 + 1 + 2),6個步驟(= 0 + 1 + 2 + 3),...)到不屬於你的進程的內存中,因爲你沒有分配它(即它是「未映射的」)。這可以解釋爲什麼mprotect在最後幾個塊中失敗。

+0

太簡單了,有些東西只需要一雙新鮮的眼睛:)非常感謝。 –