J'exécutais un script shell avec des commandes permettant d'exécuter plusieurs programmes gourmands en mémoire (2 à 5 Go) dos à dos. Lorsque je suis retourné vérifier l'état d'avancement de mon script, j'ai été surpris de découvrir que certains de mes processus étaient Killed
conformes aux instructions de mon terminal. Plusieurs programmes avaient déjà été successivement terminés avant les programmes qui ont été Killed
lancés plus tard , mais tous les programmes ont ensuite échoué dans une erreur de segmentation (qui peut ou non être due à un bogue dans mon code, continuez à lire).
J'ai examiné l'historique d'utilisation du cluster que j'utilisais et constaté qu'une personne avait commencé à exécuter plusieurs processus gourmands en mémoire en même temps, épuisant ainsi la mémoire réelle (et peut-être même l'espace de permutation) disponible pour le cluster. Autant que je sache, ces processus gourmands en mémoire ont commencé à fonctionner à peu près au même moment où j'ai commencé à avoir des problèmes avec mes programmes.
Est-il possible que Linux ait tué mes programmes une fois qu'il a commencé à manquer de mémoire? Et est-il possible que les erreurs de segmentation que j’ai eues plus tard soient dues au manque de mémoire disponible pour exécuter mes programmes (au lieu d’un bogue dans mon code)?
la source
Réponses:
Ça peut.
Il existe deux conditions de mémoire insuffisantes que vous pouvez rencontrer sous Linux. Ce que vous rencontrez dépend de la valeur de
sysctl vm.overcommit_memory
(/proc/sys/vm/overcommit_memory
)Introduction:
Le noyau peut effectuer ce que l’on appelle «mémoire surchargée». C'est à ce moment que le noyau alloue aux programmes plus de mémoire que ce qui est réellement présent dans le système. Ceci est fait dans l'espoir que les programmes n'utiliseront pas réellement toute la mémoire allouée, car il s'agit d'un événement assez courant.
surcommit_memory = 2
Lorsque
overcommit_memory
est défini sur2
, le noyau n'effectue aucune surcharge. À la place, lorsqu'un programme se voit allouer de la mémoire, l'accès à cette mémoire est garanti. Si le système ne dispose pas de suffisamment de mémoire disponible pour satisfaire une demande d'allocation, le noyau renverra simplement un échec pour la demande. Il appartient au programme de gérer la situation avec élégance. S'il ne vérifie pas que l'allocation a réussi quand elle a réellement échoué, l'application rencontrera souvent un segfault.Dans le cas du segfault, vous devriez trouver une ligne comme celle-ci dans la sortie de
dmesg
:Les
at 0
moyens que l'application a tenté d'accéder un pointeur non initialisé, ce qui peut être le résultat d'un appel d'allocation de mémoire a échoué (mais pas la seule).surcommit_memory = 0 et 1
Lorsque l'option
overcommit_memory
est définie sur0
ou1
, la surconsommation est activée et les programmes sont autorisés à allouer plus de mémoire que ce qui est réellement disponible.Cependant, lorsqu'un programme souhaite utiliser la mémoire qui lui a été allouée, mais que le noyau s'aperçoit qu'il ne dispose pas de suffisamment de mémoire pour la satisfaire, il doit récupérer de la mémoire. Il essaie d’abord d’effectuer diverses tâches de nettoyage de la mémoire, telles que le vidage des caches, mais si cela ne suffit pas, il met fin au processus. Cette terminaison est effectuée par le MOO-Killer. OOM-Killer examine le système pour voir quels programmes utilisent quelle mémoire, depuis combien de temps ils fonctionnent, qui les utilise et un certain nombre d'autres facteurs permettant de déterminer celui qui sera tué.
Une fois le processus supprimé, la mémoire qu'il utilisait est libérée et le programme qui vient de provoquer la condition de mémoire insuffisante dispose désormais de la mémoire dont il a besoin.
Toutefois, même dans ce mode, les demandes d’allocation peuvent toujours être refusées aux programmes. Le cas
overcommit_memory
échéant0
, le noyau essaie de deviner quand il devrait commencer à refuser les demandes d'allocation. Lorsqu'il est défini sur1
, je ne sais pas quelle détermination il utilise pour déterminer quand il doit refuser une demande, mais il peut refuser les demandes très volumineuses.Vous pouvez voir si OOM-Killer est impliqué en examinant le résultat
dmesg
et en recherchant des messages tels que:la source
overcommit_memory
est mis à 0 ou 2.overcommit_memory=2
le tueur de MOO n'est même pas activé, le contrôler est donc inutile. Cependant, une fois que nous établissons qu'il s'agit du tueur OOM, cela devient un autre sujet qui est couvert par de nombreuses autres questions et réponses ici.La vérité est que, quelle que soit la manière dont vous le regardez, que votre processus soit étranglé par le gestionnaire de mémoire du système ou par quelque chose d'autre, il s'agit toujours d' un bogue. Qu'est-il arrivé à toutes ces données que vous venez de traiter en mémoire? Cela aurait dû être sauvegardé.
Bien
overcommit_memory=
qu’il s’agisse du moyen le plus courant de configurer la gestion de MOO Linux, il est également possible de l’ajuster par processus, par exemple:L'utilisation
-17
de ce qui précède exclura un processus de la gestion de mémoire insuffisante. Ce n’est probablement pas une bonne idée en général, mais si vous êtes à la recherche de bogues, il pourrait en valoir la peine, surtout si vous souhaitez savoir s’il s’agissait de MOO ou de votre code. L'incrémentation positive du nombre rendra le processus plus susceptible d'être tué lors d'un événement de MOO, ce qui pourrait vous permettre de renforcer la résilience de votre code dans les situations de mémoire insuffisante et de vous assurer de sortir correctement, le cas échéant.Vous pouvez vérifier les paramètres actuels du gestionnaire de MOO par processus, comme suit:
Sinon, vous pourriez devenir suicidaire:
Cela configurera l'ordinateur pour qu'il redémarre en cas d'insuffisance de mémoire. Vous définissez ce qui
X
précède sur le nombre de secondes pendant lesquelles vous souhaitez que l'ordinateur s'arrête après une panique du noyau avant de redémarrer. Devenir fou.Et si, pour une raison quelconque, vous décidez que vous l’aimez, rendez-le persistant:
la source