Pull to refresh

Comments 17

Для рядового пользователя была бы полезна такая штука: отслеживаем в реальном времени все процессы, если какой-то из них начинает забирать слишком много памяти (например, более 3 ГБ) в течение короткого времени, ставим такой процесс на паузу (SIGSTOP), а через notification daemon отправляем пользователю уведомление — что делать с таким процессом: прибить или отпустить (SIGCONT). Может неплохо защитить от png-бомбы на 140 гигабайт, просто утечки памяти в GIMP (с ним такое нередко бывает) или просто своей кривой программы, которую программист имел неосторожность запустить на рабочей машине.
UFO just landed and posted this here
Или, знаете ли, просто возьмите systemd.
$ systemd-run --scope -p MemoryLimit=2M -p MemoryAccounting=yes ./mem
Running as unit run-818.scope.
pp[0] = 0x1473f60
...
pp[511] = 0x465cf50
Killed

Он, к тому же, отслеживает дочерние процессы контролируемого. Что будет, если к нашему big_alloc добавить fork и выделять память в нём? Что-то будет работать — qemu, lxc, я полагаю (systemd работает поверх тех же cgroups). Я хотел испытать пару упомянутых методов, но эксперименты автора не воспроизводимы. ptrace-restrict валится на этапе сборки, для lxc наверное надо контейнер создать, LD_PRELOAD не работает на изначальном примере…

Так а разве systemd-run не запустит программу под теми же cgroups? В чём тогда отличие от lxc в данном случае кроме управления через systemd и удобства?
Именно так, я это упомянул. На мой взгляд, удобства — достаточный аргумент для использования. В статье почему-то используется пример lxc-macvlan.conf, в котором создаётся сеть. Зачем она для ограничения памяти — непонятно. Можно было его урезать до задания utsname и добавить нужные лимиты.

Хм, и не понял, за что тут наминусовали. Кто-то воспроизвёл все эксперименты без проблем?
Скрытый текст
$ make ptrace-restrict
gcc -g ptrace-restrict.c -o ptrace-restrict
ptrace-restrict.c: In function ‘handle_brk’:
ptrace-restrict.c:55:32: error: ‘struct user_regs_struct’ has no member named ‘ebx’
  dbg("brk addr 0x%08X\n", state.ebx);
                                ^
ptrace-restrict.c:19:18: note: in definition of macro ‘dbg’

 make big_alloc_linker
gcc -g big_alloc.c -o big_alloc_linker -Wl,-T hack.lst
gcc-4.9.real: error: hack.lst: No such file or directory

У вас 64-битная машина?
В Windows можно было отдельную кучу для этой задачи создать и только ее использовать.
Отдельная куча в win подразумевает протаскивания своего аллокатора на ее базе по всей программе. Задумка автора была как раз ограничить память без модификации исходного кода. В win я бы посмотрел для этого в сторону объекта job.
А статья о самом решении задачи сортировки будет?
Следующим номером нашей программы.
Если вы об этой статье, то я, как автор, готов вам помочь. (Вообще не ожидал увидеть перевод своей статьи на хабр).
А вам известны решения задачи не только ограничивать память, но еще и ее сегментировать, чтобы, например, доступно было много, но выделить кусок более 64 килобайт было нельзя? У меня недавно возникла задача отладки алгоритма в условиях сегментации памяти, он падал если приложение работало долгое время. Мое решение было слишком примитивное — перед стартом алгоритма выделить много маленьких кусочков, потом через один-два освобождать.
UFO just landed and posted this here
Чтобы ограничить ресурсы с помощью cgroup не обязательно заводить отдельное окружение (lxc-контейнер). Достаточно завести свою группу, выставить ей нужные лимиты и приписать свой процесс туда. Пример:

$ cgcreate -g memory:/myGroup
$ echo $(( 500 * 1024 * 1024 )) > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes
$ echo $(( 5000 * 1024 * 1024 )) > /sys/fs/cgroup/memory/myGroup/memory.memsw.limit_in_bytes

$ cgexec -g memory:myGroup myProgramm

Утилиты для работы входят в пакет libcgroup-tools (для CentOS). При желании таким же макаром можно прописать ограничения для системных пользователей или групп.

Собственно контейнера lxc по такому принципу и работают.
Круто, я пытался сделать что-то подобное, но не смог, поэтому заюзал lxc-контейнер. По cgroups очень сложно найти какую-то внятную документацию, чтобы человек извне мог понять что вообще происходит — к чему там все эти иерархии, контроллеры и пр. и как оно, собственно, работает. Может вы напишите кратенькую статейку-ликбез на эту тему?
К сожалению, я шибко с cgroup-ами не работал и на статью не соберу.
Из граблей, на которые наступал: memsw.limit_in_bytes — это именно сумма swap+mem, и должно быть >= limit_in_bytes или лимит не установится.
По-моему сильно проще использовать malloc_usable_size() для определения размера выделенного блока. Это и будет правильный размер блока, а не то, сколько мы запрашивали. Код будет в разы проще и не нужно будет никакого хэша снаружи.
Sign up to leave a comment.

Articles