mprotect не всегда сворачивает соседние строки в /proc/pid/maps

У меня есть процесс, когда через некоторое время mprotect() не удается с ENOMEM, Ошибка вызвана тем, что "внутренние структуры ядра не могут быть размещены": в этот момент файл /proc/<pid>/maps содержит 65531 строк, что, конечно, подозрительно близко к 2^16.

Процесс начинается с получения фрагмента памяти с помощью mmap (1280 МБ, MAP_PRIVATE | MAP_ANONYMOUS) и вызова mprotect() на отдельных страницах (или небольшом количестве страниц) для включения и отключения доступа к ним, для отладки. Первоначально отображаемая область размером 1280 МБ отображается в виде одной строки в /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);

0 ответов

Другие вопросы по тегам