Como limitar o total de recursos (memória) de um processo e seus filhos

15

Há muitas perguntas e respostas sobre restringir os recursos de um único processo, por exemplo, RLIMIT_AS pode ser usado para restringir a memória máxima alocada por um processo que pode ser visto como VIRT nos gostos de top . Mais sobre o tema, por ex. aqui Existe uma maneira de limitar a quantidade de memória que um determinado processo pode usar no Unix?

setrlimit(2) documentação diz:

A child process created via fork(2) inherits its parent's resource limits. Resource limits are preserved across execve(2).

Deve ser entendido da seguinte maneira:

Se um processo tiver um RLIMIT_AS de, e. 2 GB, então ele não pode alocar mais memória do que 2 GB. Quando gera um filho, o limite de espaço de endereço de 2 GB será passado para o filho, mas a contagem começa em 0. Os dois processos juntos podem levar até 4 GB de memória.

Mas qual seria a maneira útil de restringir a soma total de memória alocada por uma árvore inteira de processos?

    
por jpe 04.06.2014 / 08:48

2 respostas

8

Não tenho certeza se isso responde à sua pergunta, mas encontrei este script perl que afirma fazer exatamente o que você procura para. O script implementa seu próprio sistema para impor os limites ao acordar e verificar o uso de recursos do processo e seus filhos. Parece estar bem documentado e explicado e foi atualizado recentemente.

Como o slm disse em seu comentário, os cgroups também podem ser usados para isso. Você pode ter que instalar os utilitários para gerenciar cgroups, supondo que você esteja no Linux, você deve procurar por libcgroups .

sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:myGroup

Certifique-se de que $USER é seu usuário.

Seu usuário deve então ter acesso às configurações de memória do cgroup em /sys/fs/cgroup/memory/myGroup .

Você pode definir o limite para, digamos 500 MB, fazendo isso:

echo 500000000 > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes

Agora vamos executar o Vim:

cgexec -g memory:myGroup vim

O processo do vim e todos os seus filhos devem estar limitados a usar 500 MB de RAM. No entanto , acho que esse limite só se aplica à RAM e não à troca. Quando os processos atingirem o limite, eles começarão a trocar. Eu não tenho certeza se você pode contornar isso, eu não consigo encontrar uma maneira de limitar o uso de swap usando cgroups.

    
por 10.06.2014 / 21:25
2

Eu criei um script que faz isso, usando o cgmanager que é usado no Ubuntu. Uma vantagem é que isso não requer acesso root. Note que o gerenciamento do cgroup é um pouco específico da distribuição, então eu não sei se isso funciona em distros que usam o gerenciamento do cd do systemd.

#!/bin/sh

set -eu

if [ "$#" -lt 2 ]
then
    echo Usage: 'basename $0' "<limit> <command>..."
    exit 1
fi

limit="$1"
shift
cgname="limitmem_$$"
echo "limiting memory to $limit (cgroup $cgname) for command $@"

cgm create memory "$cgname" >/dev/null
cgm setvalue memory "$cgname" memory.limit_in_bytes "$limit" >/dev/null
# try also limiting swap usage, but this fails if the system has no swap
cgm setvalue memory "$cgname" memsw.limit_in_bytes "$limit" >/dev/null 2>&1 || true

# spawn subshell to run in the cgroup
set +e
(
set -e
cgm movepid memory "$cgname" 'sh -c 'echo $PPID'' > /dev/null
exec "$@"
)
# grab exit code
exitcode='echo $?'

set -e

echo -n "peak memory used: "
cgm getvalue memory "$cgname" memory.max_usage_in_bytes | tail -1 | cut -f2 -d\"

cgm remove memory "$cgname" >/dev/null
exit $exitcode

uso: salve como limitmem no seu caminho e torne-o executável. Em seguida, execute, e. %código%. Isso limita a memória usada de fato. Se isso for alcançado, o killer da OOM irá matar o processo ou um dos seus filhos, mas não algo aleatório que não tenha nada a ver com este comando.

    
por 18.12.2014 / 17:35