2016-08-13 5 views
0

私はメモリブロックを割り当て、ブロックのページサイズとページアラインされたサブセットの保護を選択的に変更するプログラムを作成しようとしています。しかし、ブロックに8ページ以上あるメモリ部分にmprotectを呼び出そうとすると、mprotectは "メモリを割り当てられません"というエラーで失敗します。私が見つけたいくつかの呼び出しの後にmprotectが失敗する

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 

:次のようなメッセージを与えて、

#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:ここで

は、問題を再現し、最小限の完全な、かつ検証可能な例であります questionでは、OPが私と同じエラーを出すようですが、 David Hammenは問題の原因を示唆していますが、彼が何を話しているのか分かりません。残念ながら、OPはコードを提供していないので、彼らは何をしているのか、どうやって修正したのか正確には分かりません。

基本的に私の質問です:なぜmprotectはそのエラーを作りますか?どのように修正できますか?

+0

「私は彼が何を話しているのか分かりません」 - 正確には何が分かりませんか? – melpomene

+0

問題は、 'ENOMEM'(あなたが得るエラー)は3つの異なることを意味することがあり、意味するものがいつも分かりやすいとは限りません。 [mprotectのマニュアルページ](http://man7.org/linux/man-pages/man2/mprotect.2.html)の説明を読んだことがありますか?そこのケースの1つまたは好ましくは2つを排除できますか? –

+0

@melpomeneページがマップされているかどうか、そしてページがマッピングされているかマップされていないかを確認することによって、彼が何を意味するのか分かりません:) –

答えて

2
pointer = pointer + (n * page_size); 

この行は非常に疑わしいです。これはおそらく、0の工程で(1 + 1(= 0)をオフ歩く3(= 0 + 1 + 2)、6うpointerそうでない場合

pointer = block_addr + (n * page_size); 

又は

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

のいずれかでなければなりません(= 0 + 1 + 2 + 3)、...)を割り当てられていない(つまり、マップされていない)ため、あなたのプロセスに属していないメモリに移動します。これはなぜmprotectが最後の数チャンクで失敗するのかを説明します。

+0

うわー、とてもシンプルで、物事はちょうど目の新鮮なペアが必要ですいくつかの時間:)多くのありがとう。 –

関連する問題