Une autre façon de limiter cela consiste à utiliser les groupes de contrôle de Linux. Ceci est particulièrement utile si vous souhaitez limiter l'allocation de mémoire physique d'un processus (ou d'un groupe de processus) distinctement de la mémoire virtuelle. Par exemple :
cgcreate -g memory:myGroup
echo 500M > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes
echo 5G > /sys/fs/cgroup/memory/myGroup/memory.memsw.limit_in_bytes
va créer un groupe de contrôle nommé myGroup
, limite l'ensemble des processus exécutés sous myGroup
jusqu'à 500 Mo de mémoire physique avec memory.limit_in_bytes
et jusqu'à 5000 Mo de mémoire physique et d'échange avec memory.memsw.limit_in_bytes
.Plus d'informations sur ces options peuvent être trouvées ici :https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-memory
Pour exécuter un processus sous le groupe de contrôle :
cgexec -g memory:myGroup pdftoppm
Notez que sur une distribution Ubuntu moderne, cet exemple nécessite l'installation du cgroup-bin
package et édition /etc/default/grub
pour changer GRUB_CMDLINE_LINUX_DEFAULT
à :
GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1"
puis en exécutant sudo update-grub
et redémarrer pour démarrer avec les nouveaux paramètres de démarrage du noyau.
Si votre processus ne génère pas plus d'enfants qui consomment le plus de mémoire, vous pouvez utiliser setrlimit
fonction. L'interface utilisateur la plus courante pour cela utilise ulimit
commande du shell :
$ ulimit -Sv 500000 # Set ~500 mb limit
$ pdftoppm ...
Cela ne limitera que la mémoire "virtuelle" de votre processus, en tenant compte - et en limitant - la mémoire que le processus invoqué partage avec d'autres processus, et la mémoire mappée mais non réservée (par exemple, le grand tas de Java). Pourtant, la mémoire virtuelle est l'approximation la plus proche pour les processus qui deviennent très volumineux, ce qui rend lesdites erreurs insignifiantes.
Si votre programme génère des enfants et que ce sont eux qui allouent de la mémoire, cela devient plus complexe et vous devez écrire des scripts auxiliaires pour exécuter des processus sous votre contrôle. J'ai écrit dans mon blog, pourquoi et comment.
Il y a quelques problèmes avec ulimit. Voici une lecture utile sur le sujet :Limiter le temps et la consommation de mémoire d'un programme sous Linux, ce qui a conduit à l'outil de temporisation, qui vous permet de mettre en cage un processus (et ses fourches) en fonction du temps ou de la consommation de mémoire.
L'outil de temporisation nécessite Perl 5+ et le /proc
système de fichiers monté. Après cela, vous copiez l'outil, par ex. /usr/local/bin
comme ça :
curl https://raw.githubusercontent.com/pshved/timeout/master/timeout | \
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout
Après cela, vous pouvez "mettre en cage" votre processus en consommant de la mémoire comme dans votre question :
timeout -m 500 pdftoppm Sample.pdf
Vous pouvez également utiliser -t <seconds>
et -x <hertz>
pour limiter respectivement le processus par des contraintes de temps ou de CPU.
Le fonctionnement de cet outil consiste à vérifier plusieurs fois par seconde si le processus engendré n'a pas dépassé ses limites définies. Cela signifie qu'il y a en fait une petite fenêtre où un processus pourrait potentiellement sursouscription avant l'expiration du délai et tue le processus.
Une approche plus correcte impliquerait donc probablement des cgroups, mais cela est beaucoup plus complexe à mettre en place, même si vous utilisez Docker ou runC, qui, entre autres, offrent une abstraction plus conviviale autour des cgroups.