Использование памяти дочерним процессом? - PullRequest
6 голосов
/ 13 апреля 2009

Я запускаю своего рода «песочницу» в C на Ubuntu: она берет программу и безопасно запускает ее под пользователем nobody (и перехватывает сигналы и т. Д.). Кроме того, он назначает память и ограничения по времени, а также измеряет время и использование памяти.
(Если вам интересно, это своего рода «онлайн-судья», чтобы отмечать программы на тестовых данных)

В настоящее время я адаптировал модуль safeexec из mooshak . Хотя большинство вещей работает должным образом, использование памяти кажется проблемой. (Это очень неточно)

Теперь я попробовал совет здесь и проанализировал ВМ из /proc/pid/stat, и теперь проблема с точностью устранена. Однако, для программ, которые завершаются очень быстро, это не работает и просто возвращает 0.

Программа safeexec работает следующим образом:

  1. Это fork() с
  2. Использует execv() в дочернем процессе для запуска нужной программы
  3. Контролирует программу из родительского процесса до тех пор, пока дочерний процесс не завершится (используя wait4, что возвращает использование ЦП, но не память?)
    Таким образом, он анализирует /proc/../stat дочернего процесса (который был заменен execv)

Так почему ВМ в /proc/child_pid/stat иногда равна 0?
Это потому, что execv () завершается слишком быстро, а /proc/child_pid/stat просто недоступен?
Если да, есть ли какой-нибудь другой способ получить использование памяти ребенком?
(Так как это предназначено для оценки программ с ограничением по времени, я не могу позволить себе что-то со снижением производительности, как valgrind)

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 13 апреля 2009

Можете ли вы договориться, чтобы дочерний процесс использовал вашу собственную версию malloc() и др. И вел ли этот журнал использование памяти HWM (возможно, с помощью обработчика, зарегистрированного в atexit())? Возможно, вы бы использовали LD_PRELOAD для загрузки библиотеки управления памятью. Это не поможет с огромными статическими массивами или огромными автоматическими массивами.


Хм, звучит интересно. Есть ли способ отследить статические / автоматические массивы?

Статическая память может быть проанализирована с помощью команды «size» - более или менее.

Проблемы с автоматическими массивами - я не уверен, как вы справитесь с этим. Ваш код выделения памяти может посмотреть, сколько стека используется, когда он вызывается (посмотрите на адрес локальной переменной). Но нет никакой гарантии, что память будет выделена, когда используется максимальное количество локального массива, так что это дает в лучшем случае грубую меру.

Еще одна мысль: возможно, вы могли бы использовать технологию отладчика - системный вызов ptrace() - для управления дочерним процессом и, в частности, для его удержания достаточно долго, чтобы иметь возможность собирать статистику использования памяти из /proc/....

2 голосов
/ 13 апреля 2009

Вы можете установить ограничение жесткого ресурса (setrlimit для ресурса RLIMIT_AS) перед execve (). Программа не сможет выделить больше этого объема памяти. Если он попытается это сделать, вызовы выделения памяти (brk, mmap, mremap) завершатся неудачно. Если программа не обрабатывает состояние нехватки памяти, то возникает ошибка, которая будет отражена в состоянии выхода, возвращаемом wait4.

0 голосов
/ 25 марта 2018

Вы можете использовать функцию getrusage (2) из ​​библиотеки sys / resources.h.
Ссылка: https://linux.die.net/man/2/getrusage
Эта функция использует структуру «rusage», которая содержит поле ru_maxrss, в котором хранится информация о наибольшем использовании дочерней памяти из всех дочерних процессов, которые были у текущего процесса.
Эта функция также может быть выполнена из основного процесса после завершения всех дочерних процессов.
Чтобы получить информацию, попробуйте что-то вроде этого:

struct rusage usage;
int a = getrusage(RUSAGE_CHILDREN, &usage);

Но тут есть маленькая хитрость.
Если вы хотите получить информацию о том, как каждый дочерний процесс использует память (не только самую большую), вы должны дважды выполнить fork () вашей программы (первый форк позволяет вам иметь независимый процесс, а второй - процесс, который вы хотите протестировать .

...