しばらくすると、 への呼び出しが で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);