it-swarm.com.de

Wird Linux anfangen, meine Prozesse zu beenden, ohne mich zu fragen, ob der Speicher knapp wird?

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 Killed waren, wie mein Terminal mir berichtete. Einige Programme wurden bereits nacheinander abgeschlossen, bevor die Programme Killed gestartet wurden, aber alle Programme scheiterten danach an einem Segmentierungsfehler (der möglicherweise auf einen Fehler in meinem Code zurückzuführen war oder nicht, lesen Sie weiter).

Ich habe mir den Nutzungsverlauf des von mir verwendeten Clusters angesehen und festgestellt, dass jemand mehrere speicherintensive Prozesse gleichzeitig ausgeführt hat und dabei den tatsächlichen Speicher (und möglicherweise sogar den dem Cluster zur Verfügung stehenden Auslagerungsspeicher) erschöpft hat. Soweit ich das beurteilen kann, wurden diese speicherintensiven Prozesse ungefähr zu der Zeit ausgeführt, als ich Probleme mit meinen Programmen hatte.

Ist es möglich, dass Linux meine Programme beendet hat, als der Speicher knapp wurde? 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 verfügbar ist (anstelle eines Fehlers in meinem Code)?

69
NeutronStar

Es kann.

Unter Linux können zwei verschiedene Speicherprobleme auftreten. 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 den Programmen mehr Speicher zu, als tatsächlich im System vorhanden ist. Dies geschieht in der Hoffnung, dass die Programme nicht den gesamten von ihnen zugewiesenen Speicher nutzen, da dies häufig vorkommt.

overcommit_memory = 2

Wenn overcommit_memory Auf 2 Gesetzt ist, führt der Kernel überhaupt kein Overcommit durch. Wenn einem Programm stattdessen Speicher zugewiesen wird, wird der Zugriff auf diesen Speicher garantiert. Wenn das System nicht über genügend freien Speicher verfügt, um eine Zuordnungsanforderung zu erfüllen, gibt der Kernel nur einen Fehler für die Anforderung zurück. Es ist Sache des Programms, mit der Situation angemessen umzugehen. Wenn nicht überprüft wird, ob die Zuordnung erfolgreich war, wenn sie wirklich fehlgeschlagen ist, tritt bei der Anwendung häufig ein Segfault auf.

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

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

at 0 Bedeutet, dass die Anwendung versucht hat, auf einen nicht initialisierten Zeiger zuzugreifen. Dies kann das Ergebnis eines fehlgeschlagenen Speicherzuweisungsaufrufs sein (dies ist jedoch nicht die einzige Möglichkeit).

overcommit_memory = 0 und 1

Wenn overcommit_memory Auf 0 Oder 1 Eingestellt ist, ist Overcommit aktiviert und Programme können mehr Speicher zuweisen, als tatsächlich verfügbar ist.

Wenn ein Programm den ihm zugewiesenen Speicher verwenden möchte, der Kernel jedoch feststellt, dass er nicht über genügend Speicher verfügt, um ihn zu befriedigen, muss er etwas Speicher zurückerhalten. 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 verwenden, 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 Speichermangel verursacht hat, verfügt nun über den benötigten Speicher.

Selbst in diesem Modus können Programmen jedoch weiterhin Zuordnungsanforderungen verweigert werden. Wenn overcommit_memory0 Ist, versucht der Kernel zu erraten, wann er anfangen sollte, Zuordnungsanforderungen abzulehnen. Wenn es auf 1 Eingestellt ist, bin ich mir nicht sicher, mit welcher Bestimmung bestimmt wird, wann eine Anforderung abgelehnt werden soll, aber es können sehr große Anforderungen abgelehnt werden.

Sie können feststellen, ob der OOM-Killer beteiligt ist, indem Sie sich die Ausgabe von dmesg ansehen und folgende Nachrichten suchen:

[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
76
Patrick

Die Wahrheit ist, dass es unabhängig davon, wie Sie es betrachten - ob Ihr Prozess aufgrund des Speichermanagers des Systems oder aufgrund von etwas anderem verstopft ist - immer noch ein Fehler ist. Was ist mit all den Daten passiert, die Sie gerade im Speicher verarbeitet haben? Es sollte gespeichert worden sein.

Während overcommit_memory= ist die allgemeinste Methode zum Konfigurieren der Linux-OOM-Verwaltung. Sie kann auch pro Prozess angepasst werden, z.

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

Verwenden von -17 oben schließt einen Prozess von der Speicherverwaltung aus. Wahrscheinlich im Allgemeinen keine gute Idee, aber wenn Sie auf Fehlersuche sind, könnte sich dies lohnen - insbesondere, wenn Sie wissen möchten, ob es sich um OOM oder Ihren Code handelt. Wenn Sie die Anzahl positiv erhöhen, wird die Wahrscheinlichkeit erhöht, dass der Prozess bei einem OOM-Ereignis abgebrochen wird. Dies kann es Ihnen ermöglichen, die Ausfallsicherheit Ihres Codes in Situationen mit wenig Arbeitsspeicher besser zu stärken und sicherzustellen, 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 

Sonst könnten Sie Selbstmord begehen:

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

Dadurch wird der Computer bei einem Speichermangel neu gestartet. Sie setzen X oben auf die Anzahl der Sekunden, die der Computer nach einer Kernel-Panik vor dem Neustart anhalten soll. Dreh durch.

Und wenn Sie aus irgendeinem Grund entscheiden, dass es Ihnen gefällt, machen Sie es hartnäckig:

echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf
16
mikeserv