Come limitare le risorse totali (memoria) di un processo e dei suoi figli


16

Esistono molte domande e risposte sulla limitazione delle risorse di un singolo processo, ad esempio RLIMIT_AS può essere utilizzato per limitare la memoria massima allocata da un processo che può essere visto come VIRT come top. Maggiori informazioni sull'argomento, ad esempio qui Esiste un modo per limitare la quantità di memoria che un determinato processo può utilizzare in Unix?

setrlimit(2) la documentazione dice:

Un processo figlio creato tramite fork (2) eredita i limiti delle risorse dei suoi genitori. I limiti delle risorse vengono mantenuti in execve (2).

Dovrebbe essere compreso nel modo seguente:

Se un processo ha un RLIMIT_AS, ad esempio 2 GB, non può allocare più memoria di 2 GB. Quando genera un figlio, il limite di 2 GB di spazio indirizzo verrà passato al figlio, ma il conteggio inizia da 0. I 2 processi insieme possono richiedere fino a 4 GB di memoria.

Ma quale sarebbe il modo utile di limitare la somma totale della memoria allocata da un intero albero di processi?



7
Darei un'occhiata ai cgroups .
slm

@slm Grazie! Sembra che i cgroups siano qualcosa da provare. L'unica soluzione funzionante finora (oltre a un brutto modo di sommare la memoria usando PS e uccidere il processo genitore se sopra il limite) che potrebbe funzionare sta usando una qualche forma di un contenitore (lxc o simili).
jpe

Sì, gli strumenti di cui sono a conoscenza non fanno un gruppo, solo singoli processi, ma dato come funzionano i cgroup per le tecnologie VM come LXC e Docker, mi aspetto che faccia quello che vuoi.
slm

1
Se è Linux metti il ​​PID padre nel suo spazio dei nomi e controlla in questo modo e tutti i suoi figli. Ecco una risposta introduttiva a questo concetto: unix.stackexchange.com/a/124194/52934
mikeserv

Risposte:


8

Non sono sicuro che questo risponda alla tua domanda, ma ho trovato questo script perl che afferma di fare esattamente quello che stai cercando. La sceneggiatura implementa un proprio sistema per far rispettare i limiti risvegliandosi e controllando l'utilizzo delle risorse del processo e dei suoi figli. Sembra essere ben documentato e spiegato, ed è stato aggiornato di recente.

Come ha detto slm nel suo commento, i cgroups possono anche essere usati per questo. Potrebbe essere necessario installare i programmi di utilità per la gestione dei cgroups, supponendo che tu sia su Linux che dovresti cercare libcgroups.

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

Assicurati che $USERsia il tuo utente.

L'utente dovrebbe quindi avere accesso alle impostazioni della memoria del cgroup in /sys/fs/cgroup/memory/myGroup.

È quindi possibile impostare il limite su, diciamo 500 MB, in questo modo:

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

Ora eseguiamo Vim:

cgexec -g memory:myGroup vim

Il processo vim e tutti i suoi figli dovrebbero ora essere limitati all'utilizzo di 500 MB di RAM. Tuttavia , penso che questo limite si applichi solo alla RAM e non allo scambio. Una volta che i processi hanno raggiunto il limite, inizieranno a scambiarsi. Non sono sicuro che sia possibile aggirare questo problema, non riesco a trovare un modo per limitare l'utilizzo degli swap utilizzando i cgroups.


La soluzione proposta consente di limitare la dimensione dell'insieme residente di un albero di processi. Il comportamento sembra essere diverso da RLIMIT_AS: è possibile mallocare più memoria di quanto non sia il limite, tuttavia sembra che non sia possibile utilizzarne effettivamente di più.
jpe,

Per impostazione predefinita, il limite di memoria del cgroup si applica solo (approssimativamente) all'uso della RAM fisica. C'è un'opzione del kernel (CONFIG_MEMCG_SWAP) per abilitare la contabilità di swap; vedere i documenti del kernel per i dettagli.
Søren Løvborg,

1
Su fedora,sudo yum install libcgroup-tools
jozxyqk,

2

Ho creato uno script che fa questo, usando cgmanager che viene usato in Ubuntu. Un vantaggio è che questo non richiede l'accesso come root. Nota che la gestione di cgroup è un po 'specifica per la distribuzione, quindi non so se questo funziona su distro che usano la gestione di cgroup di 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

utilizzo: salva come limitmemnel tuo percorso e rendilo eseguibile. Quindi eseguire ad es limitmem 1G command.... Ciò limita la memoria effettivamente utilizzata. Se viene raggiunto, il killer OOM ucciderà il processo o uno dei suoi figli, ma non qualcosa di casuale che non ha nulla a che fare con questo comando.


Grazie per la breve cgmguida, è stato utile
Vitaly Isaev il

1

/unix//a/536046/4319 :

Su qualsiasi distribuzione basata su systemd è inoltre possibile utilizzare i cgroup indirettamente tramite systemd-run. Ad esempio, nel caso in cui si limiti pdftoppma 500 M di RAM, utilizzare:

systemd-run --scope -p MemoryLimit=500M pdftoppm

...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.