Fängt Linux an, meine Prozesse zu beenden, ohne mich zu fragen, ob der Speicher knapp wird?

66

Ich habe ein Shell-Skript mit Befehlen ausgeführt, um mehrere speicherintensive Programme (2-5 GB) hintereinander auszuführen. Als ich zurückging, um den Fortschritt meines Skripts zu überprüfen, stellte ich überrascht fest, dass einige meiner Prozesse so abliefen Killed, wie mein Terminal es mir meldete. Einige Programme wurden bereits nacheinander beendet, bevor die später Killedgestarteten Programme ausgeführt wurden , aber alle Programme scheiterten danach an einem Segmentierungsfehler (der möglicherweise auf einen Fehler in meinem Code zurückzuführen war, lesen Sie weiter).

Ich habe mir den Nutzungsverlauf des von mir verwendeten Clusters angesehen und festgestellt, dass jemand mehrere speicherintensive Prozesse gleichzeitig ausführt, wodurch der dem Cluster zur Verfügung stehende reale Speicher (und möglicherweise sogar der Swap-Speicher) erschöpft wird. Soweit ich es beurteilen kann, begannen diese speicherintensiven Prozesse ungefähr zu der Zeit zu laufen, als ich anfing, Probleme mit meinen Programmen zu haben.

Ist es möglich, dass Linux meine Programme beendet hat, nachdem der Speicher aufgebraucht war? Und ist es möglich, dass die Segmentierungsfehler, die ich später bekam, auf den Mangel an Speicher zurückzuführen sind, der zum Ausführen meiner Programme zur Verfügung steht (anstelle eines Fehlers in meinem Code)?

NeutronStar
quelle
2
Haben Sie beim Zuweisen von Speicher eine Anweisung, um zu überprüfen, ob der Speicher erfolgreich zugewiesen wurde? Das sollte einen Hinweis darauf geben, ob Ihr Code fehlerhaft ist oder ob es an einem Speichermangel im System lag.
Unxnut

Antworten:

72

Es kann.

Es gibt zwei verschiedene Bedingungen für nicht genügend Arbeitsspeicher, die unter Linux auftreten können. Was Ihnen begegnet, hängt vom Wert von sysctl vm.overcommit_memory( /proc/sys/vm/overcommit_memory) ab.

Einführung:
Der Kernel kann ein sogenanntes 'Memory Overcommit' ausführen. In diesem Fall weist der Kernel Programmen mehr Speicher zu, als tatsächlich im System vorhanden ist. Dies geschieht in der Hoffnung, dass die Programme nicht den gesamten zugewiesenen Speicher belegen, da dies häufig vorkommt.

overcommit_memory = 2

Wenn auf overcommit_memorygesetzt, 2führt der Kernel überhaupt kein Overcommit durch. Wenn einem Programm stattdessen Speicher zugewiesen wird, ist der Zugriff auf diesen Speicher garantiert. Wenn das System nicht über genügend freien Speicher verfügt, um eine Zuweisungsanforderung zu erfüllen, gibt der Kernel nur einen Fehler für die Anforderung zurück. Es ist Aufgabe des Programms, mit der Situation angemessen umzugehen. Wenn nicht überprüft wird, ob die Zuweisung erfolgreich war, obwohl sie tatsächlich fehlgeschlagen ist, stößt die Anwendung häufig auf einen Segfault.

Im Falle des Segfault sollten Sie eine solche Zeile in der Ausgabe von finden dmesg:

[1962.987529] myapp[3303]: segfault at 0 ip 00400559 sp 5bc7b1b0 error 6 in myapp[400000+1000]

Die at 0bedeutet , dass die Anwendung versucht , einen nicht initialisierten Zeiger zuzugreifen, die das Ergebnis einer fehlerhaften Speicherzuweisungsaufruf sein kann (aber es ist nicht die einzige Art und Weise).

overcommit_memory = 0 und 1

Wenn overcommit_memoryauf 0oder gesetzt ist 1, ist das Overcommit aktiviert, und Programme können mehr Speicher zuweisen, als tatsächlich verfügbar ist.

Wenn ein Programm jedoch den zugewiesenen Speicher verwenden möchte, der Kernel jedoch feststellt, dass nicht genügend Speicher vorhanden ist, um die Anforderungen zu erfüllen, muss ein Teil des Speichers zurückerhalten werden. Zunächst wird versucht, verschiedene Speicherbereinigungsaufgaben auszuführen, z. B. das Leeren von Caches. Wenn dies jedoch nicht ausreicht, wird ein Prozess beendet. Diese Kündigung wird vom OOM-Killer durchgeführt. Der OOM-Killer untersucht das System, um festzustellen, welche Programme welchen Speicher belegen, wie lange sie ausgeführt wurden, wer sie ausführt und eine Reihe anderer Faktoren, um festzustellen, welche Programme getötet werden.

Nachdem der Prozess beendet wurde, wird der von ihm verwendete Speicher freigegeben, und das Programm, das gerade den Zustand außerhalb des Speichers verursacht hat, verfügt jetzt über den benötigten Speicher.

Auch in diesem Modus können Programmen Zuweisungsanforderungen verweigert werden. Wann dies der Fall overcommit_memoryist 0, versucht der Kernel zu erraten, wann er anfangen sollte, Zuweisungsanforderungen abzulehnen. Wenn es auf festgelegt ist 1, bin ich nicht sicher, welche Bestimmung es verwendet, um zu bestimmen, wann es eine Anforderung ablehnen sollte, aber es kann sehr große Anforderungen ablehnen.

Sie können feststellen, ob der OOM-Killer involviert ist, indem Sie die Ausgabe von dmesgund nach Nachrichten suchen , wie zum Beispiel:

[11686.043641] Out of memory: Kill process 2603 (flasherav) score 761 or sacrifice child
[11686.043647] Killed process 2603 (flasherav) total-vm:1498536kB, anon-rss:721784kB, file-rss:4228kB
Patrick
quelle
Es scheint also, dass mir beide Situationen passiert sind.
NeutronStar
@ Joshua Ich habe gerade die Antwort aktualisiert. Ich habe vergessen zu erwähnen, dass es immer noch zu Zuordnungsfehlern kommen kann, wenn overcommit_memory0 oder 2 eingestellt ist.
Patrick
Ich denke, dass es sich lohnen könnte, einen Link zu Taming the OOM Killer in den Post zu schreiben .
0xC0000022L
@ 0xC0000022L Danke, das ist ein guter Artikel (wenn auch etwas veraltet). Ich wollte nichts über die Kontrolle des OOM-Killers sagen, da dies nicht Teil der Frage ist (und es ist kein kurzes Thema), und wir haben hier eine Menge anderer Fragen zu genau diesem Thema.
Patrick
1
@mikeserv Ich sage nicht, dass das Verhalten des OOM-Killers nichts damit zu tun hat, es zu kontrollieren. Die Frage war, ob Linux seine Programme beenden würde. Um zu verhindern, dass Linux dies tut, muss zunächst festgestellt werden, dass es sich tatsächlich um Linux handelt. Und wenn overcommit_memory=2der OOM-Killer nicht einmal aktiviert ist, ist die Steuerung irrelevant. Sobald wir jedoch feststellen, dass es sich um den OOM-Killer handelt, wird dies zu einem weiteren Thema, das hier von vielen anderen Fragen und Antworten behandelt wird.
Patrick
16

Die Wahrheit ist, dass es immer noch ein Fehler ist, unabhängig davon, wie Sie es betrachten - ob Ihr Prozess durch den Speichermanager des Systems oder durch etwas anderes blockiert ist. Was ist mit all den Daten passiert, die Sie gerade im Speicher verarbeitet haben? Es hätte gerettet werden sollen.

Während overcommit_memory=die allgemeinste Art und Weise Linux OOM Verwaltung der Konfiguration ist es auch einstellbar pro Prozess wie:

echo [-+][n] >/proc/$pid/oom_adj

Bei Verwendung -17der oben genannten Option wird ein Prozess von der Speichermangelverwaltung ausgeschlossen. Wahrscheinlich keine gute Idee im Allgemeinen, aber wenn Sie nach Fehlern suchen, kann sich dies lohnen - insbesondere, wenn Sie wissen möchten, ob es sich um OOM oder Ihren Code handelt. Eine positive Erhöhung der Anzahl erhöht die Wahrscheinlichkeit, dass der Prozess bei einem OOM-Ereignis abgebrochen wird, wodurch Sie die Ausfallsicherheit Ihres Codes in Situationen mit wenig Arbeitsspeicher verbessern und sicherstellen können, dass Sie bei Bedarf ordnungsgemäß beendet werden.

Sie können die aktuellen Einstellungen des OOM-Handlers pro Prozess wie folgt überprüfen:

cat /proc/$pid/oom_score 

Andernfalls könnten Sie Selbstmord begehen:

sysctl vm.panic_on_oom=1
sysctl kernel.panic=X

Dadurch wird der Computer für den Fall eines Speichermangels neu gestartet. Sie stellen die XAnzahl der Sekunden ein, die der Computer nach einer Kernel-Panik vor dem Neustart anhalten soll. Dreh durch.

Und wenn Sie es aus irgendeinem Grund mögen, lassen Sie es hartnäckig werden:

echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf
mikeserv
quelle
Ich verwende einen gemeinsam genutzten Cluster. Ich bin sicher, die anderen Benutzer würden einen Neustart ohne deren Zustimmung nicht begrüßen.
NeutronStar
3
@Joshua - Ich bezweifle sehr ernsthaft, dass es jemandem gefallen würde - es widerspricht sogar Asimovs Gesetzen der Robotik. Auf der anderen Seite können Sie, wie bereits erwähnt, das OOM pro Prozess auch auf die andere Weise konfigurieren. Das heißt, Sie können anhand Ihrer eigenen definierten Regelsätze pro Prozess eine persönliche Triage durchführen. Das klingt so, als wäre es in einem Szenario mit gemeinsam genutzten Clustern besonders nützlich.
mikeserv