4

しばらくすると、 への呼び出しが でmprotect()失敗するプロセスがありますENOMEM。このエラーは、「内部カーネル構造を割り当てることができませんでした」が原因で発生します。この時点で、ファイル/proc/<pid>/mapsには 65531 行が含まれており、これはもちろん疑わしいほど 2^16 に近いものです。

プロセスは、mmap (1280MB、MAP_PRIVATE | MAP_ANONYMOUS) でメモリのチャンクを取得することから始まり、mprotect()単一ページ (または少数のページ) を呼び出して、デバッグのためにそれらへのアクセスを有効または無効にします。1280MB の mmaped 領域は、最初は では 1 行として表示されます/proc/<pid>/mapsが、 を呼び出すたびに、mprotect()この領域が 3 つに「分割」される可能性があります。前のメモリ、変更されたページ、後のメモリです。いくつかの変更の後、2 つの隣接する (ただし個別に変更された) メモリ領域が同じアクセス フラグで終わると、通常は再びマージされるため、行の総数は適切に保たれます。

ただし「通常」のみ。失敗した場合/proc/<pid>/maps、同じ保護を持つ多数の連続したメモリ領域が作成され、それらがマージされない理由がわかりません。1 ページの例では、それらは適切にマージされます。動作が異なるのはいつで、その理由は?

参考までに、失敗したプログラムはマルチスレッドですが、影響はありません (各スレッドの/proc/<tid>/mapsファイルは同一です)。Linux カーネル「2.6.35-30-generic #56-Ubuntu SMP」および「3.2.0-37-generic #58-Ubuntu SMP」で見られます。

編集:再現方法:

hg clone https://bitbucket.org/pypy/stmgc
cd stmgc/c4
hg up d4e3aac8c458     # branch copy-over-original2
make debug-demo2
gdb ./debug-demo2      # lots and lots of colored output

で失敗するはずですerr = mprotect(..); assert(err == 0);

4

0 に答える 0