72 lines
3.1 KiB
Markdown
72 lines
3.1 KiB
Markdown
\newpage
|
|
|
|
Gestion de la mémoire
|
|
=====================
|
|
|
|
Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : par
|
|
défaut, `malloc(3)` ne retournera jamais `NULL`. En se basant sur l'euristique
|
|
qu'un bloc mémoire demandé ne sera pas utilisé directement et que de nombreux
|
|
process ne feront pas un usage total des blocks qu'ils ont alloués, le noyau
|
|
permet d'allouer plus de mémoire qu'il n'y en a réellement disponible. La
|
|
mémoire est donc utilisée de manière plus efficace.
|
|
|
|
[^vm-overcommit]: Dépendant de la valeur de `/proc/sys/vm/overcommit_memory`,
|
|
généralement 0. Voir
|
|
<https://www.kernel.org/doc/Documentation/vm/overcommit-accounting>.
|
|
|
|
Mais évidemment, cela peut donner lieu à des situations où le noyau n'est plus
|
|
en mesure de trouver de bloc physiquement disponible, alors qu'ils avaient
|
|
effectivement été alloués au processus. Pour autant, ce n'est pas une raison
|
|
pour tuer ce processus, car il est peut-être vital pour le système (peut-être
|
|
est-ce `init` qui est en train de gérer le lancement d'un nouveau daemon). On
|
|
dit alors que le noyau est *Out-Of-Memory*.
|
|
|
|
Pour se sortir d'une telle situation, et après avoir tenté de vider les caches,
|
|
il lance son arme ultime, pour retrouver au plus vite de la mémoire :
|
|
l'*Out-Of-Memory killer*.
|
|
|
|
|
|
## OOM killer
|
|
|
|
Selon un algorithme dont on raconte qu'il ne serait pas basé entièrement sur
|
|
l'aléatoire[^oom-algo], un processus est tiré au sort (plus un processus occupe
|
|
de mémoire et plus il a de chance d'être tiré au sort) par l'OOM killer. Le
|
|
sort qui lui est réservé est tout simplement une mort brutale. Pour permettre
|
|
au système de disposer à nouveau de mémoire disponible. Si cela n'est pas
|
|
suffisant, un ou plusieurs autres processus peuvent être tués à tour de rôle,
|
|
jusqu'à ce que le système retrouve sa sérénité.
|
|
|
|
[^oom-algo]: ```c
|
|
/*
|
|
* oom_badness - calculate a numeric value for how bad this task has been
|
|
* @p: task struct of which task we should calculate
|
|
* @p: current uptime in seconds
|
|
*
|
|
* The formula used is relatively simple and documented inline in the
|
|
* function. The main rationale is that we want to select a good task
|
|
* to kill when we run out of memory.
|
|
*
|
|
* Good in this context means that:
|
|
* 1) we lose the minimum amount of work done
|
|
* 2) we recover a large amount of memory
|
|
* 3) we don't kill anything innocent of eating tons of memory
|
|
* 4) we want to kill the minimum amount of processes (one)
|
|
* 5) we try to kill the process the user expects us to kill, this
|
|
* algorithm has been meticulously tuned to meet the principle
|
|
* of least surprise ... (be careful when you change it)
|
|
*/```
|
|
|
|
|
|
## Esquiver l'OOM killer
|
|
|
|
Au sein d'un *cgroup* *memory*, le fichier `memory.oom_control` peut être
|
|
utilisé afin de recevoir une notification du noyau avant que l'OOM-killer
|
|
ne s'attaque à un processus de ce groupe.
|
|
|
|
Grâce à cette notification, il est possible de figer le processus pour
|
|
l'envoyer sur une autre machine. Et ainsi libérer la mémoire avant que l'OOM
|
|
killer ne passe.
|
|
|
|
Jetez un œil à [cet article parru LVM](https://lwn.net/Articles/590960/) à ce
|
|
sujet.
|