4

我有一个过程,一段时间后,调用mprotect()失败并显示ENOMEM. 该错误是由“无法分配内部内核结构”引起的:此时,该文件/proc/<pid>/maps包含 65531 行,这当然是可疑的接近 2^16。

该过程首先使用 mmap (1280MB, MAP_PRIVATE | MAP_ANONYMOUS) 获取一块内存,然后mprotect()在单个页面(或少量页面)上调用以启用和禁用对它们的访问,以进行调试。1280MB 映射区域最初显示为 中的一行/proc/<pid>/maps,但每次调用mprotect()都可能将该区域“拆分”为三部分:之前的内存、修改后的页面和之后的内存。经过多次更改,当两个相邻(但独立修改)的内存区域最终具有相同的访问标志时,通常会再次合并它们,因此总行数保持合理。

但只是“通常”。在失败的情况下,/proc/<pid>/maps最终会产生大量具有相同保护的连续内存区域,我不明白为什么它们不合并。在单页示例中,它们被正确合并。什么时候它的工作方式不同,为什么?

作为参考,失败的程序是多线程的,尽管这不应该产生影响(对于每个线程,/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