Wie löst man bei geringem Arbeitsspeicher in Linux eine Aktion aus?

Wie löst man bei geringem Arbeitsspeicher in Linux eine Aktion aus?

Daher dachte ich, dass dies ziemlich einfach zu finden wäre: ein Dienst-/Kernelmodul, das, wenn der Kernel feststellt, dass der Benutzerlandspeicher zur Neige geht, eine Aktion auslöst (z. B. eine Prozessliste in eine Datei schreiben, einen Netzwerk-Endpunkt anpingen usw.) innerhalb eines Prozesses, der über seinen eigenen dedizierten Speicher verfügt (damit fork() nicht fehlschlägt oder andere übliche OOM-Probleme auftreten).

ich fand dieOOM-Killer, was meines Wissens nach nützlich ist, aber nicht wirklich das tut, was ich tun muss.

Wenn mir der Speicher ausgeht, möchte ich im Idealfall wissen, warum. Ich könnte wohl mein eigenes Programm schreiben, das beim Start ausgeführt wird und eine feste Speichermenge verwendet und dann nur dann etwas ausführt, wenn es vom Kernel über zu wenig Speicher informiert wird, aber das wirft eine eigene Frage auf ...

Gibt es überhaupt einen Systemaufruf, um über so etwas informiert zu werden? Eine Möglichkeit, dem Kernel zu sagen: „Hey, weck mich auf, wenn wir nur noch 128 MB Speicher übrig haben“?

Ich habe im Internet und hier gesucht, aber nichts gefunden, das dieser Beschreibung entspricht. Die meisten Leute scheinen Polling mit Zeitverzögerung zu verwenden, aber das offensichtliche Problem dabei ist, dass es viel unwahrscheinlicher wird, dass Sie herausfinden können, welcher Prozess bzw. welche Prozesse das Problem verursacht haben.

Antwort1

Ja, der Linux-Kernel bietet hierfür einen Mechanismus:Benachrichtigung über zu geringen SpeicherbedarfDies ist dokumentiert inhttps://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt, AbschnittSpeicherdruck.

Kurz gesagt, Sie registrieren einen Eventfd-Dateideskriptor in , in /sys/fs/cgroup/memory/memory.pressure_leveldem Sie Benachrichtigungen erhalten möchten. Diese Benachrichtigungen können low, medium, oder sein critical. Ein typischer Anwendungsfall wäre, einige oder alle internen Caches in Ihrem Prozess freizugeben, wenn Sie eine Benachrichtigung erhalten, um einen drohenden OOM-Kill zu verhindern.

Antwort2

Was Sie im Grunde fragen, ist ein kernelbasierter Rückruf bei zu wenig Arbeitsspeicher, richtig? Wenn ja, bin ich fest davon überzeugt, dass der Kernelnichteinen solchen Mechanismus bereitzustellen,und das aus gutem Grund:Wenn der Arbeitsspeicher knapp wird, sollte sofort das einzige Programm ausgeführt werden, das Speicher freigeben kann - der OOM-Killer. Alle anderen Programme können den Computer zum Stillstand bringen.

Wie auch immer, Sie können eine einfache Überwachungslösung im Benutzerbereich ausführen. Ich hatte in der Vergangenheit die gleiche Debug-/Aktionsanforderung mit geringem Arbeitsspeicher und habe eine einfache Bash geschrieben, die Folgendes tat:

  • Monitor für eineweiches Wasserzeichen:Wenn die Speichernutzung diesen Schwellenwert überschreitet, erfassen Sie einige Statistiken (Prozesse, freier/genutzter Speicher usw.) und senden Sie eine Warn-E-Mail.

  • Monitor für einehartes Wasserzeichen:Wenn die Speichernutzung diesen Grenzwert überschreitet, erfassen Sie einige Statistiken und beenden Sie die speicherhungrigeren (oder weniger wichtigen) Prozesse. Senden Sie anschließend eine Warn-E-Mail.

Ein solches Skript wäre sehr leicht und könnte die Maschine in kurzen Abständen (z. B. 15 Sekunden) abfragen.

Antwort3

Die derzeit beste Lösung ist für cgroups-v1. Für cgroups-v2 kann man auf Dateiänderungsereignisse in der memory.eventsDatei warten (Dokumentationdes Dateiinhalts).

Das Verhalten dieser Datei kann tatsächlich mit einigen Shell-Befehlen getestet werden:

# Spawn a new slice with memory limits to avoid OOMing the entire system
systemd-run --pty --user -p MemoryMax=1050M -p MemoryHigh=1000M bash

# Watch memory.events for changes and read when changed
inotifywait -e modify -m /sys/fs/cgroup$(cut -d: -f3 /proc/self/cgroup)/memory.events \
  | while read l; do echo $l; cat ${l// *}; done &
# Consume memory
tail /dev/zero

Leider scheint dies nur zu funktionieren, wenn tatsächlich ein Speicherlimit für die Cgroup festgelegt ist. Alternativ kann manHören Sie sich Memory.Pressure an, aber das ist nicht cgroup-basiert (zumindest für Nicht-Root-Benutzer) und reagiert nicht ganz so schnell.

verwandte Informationen