Ich bin kein Kernel-Entwickler, aber ich habe jahrelang über dieses Thema philosophiert, weil ich soooo oft darauf gestoßen bin. Ich habe mir tatsächlich eine Metapher für die ganze Situation ausgedacht, also lassen Sie mich Ihnen das sagen. Ich gehe in meiner Geschichte davon aus, dass Dinge wie "Swap" nicht existieren. Mit 32 GB RAM macht Swap heutzutage ohnehin wenig Sinn.
Stellen Sie sich ein Viertel von Ihnen vor, in dem Wasser durch Rohre an jedes Gebäude angeschlossen wird und die Städte die Kapazität verwalten müssen. Nehmen wir an, Sie haben nur eine Produktion von 100 Einheiten Wasser pro Sekunde (und die gesamte ungenutzte Kapazität geht verloren, weil Sie keine Reservoirtanks haben). Jedes Zuhause (Zuhause = eine kleine App, ein Terminal, das Uhr-Widget usw.) benötigt eine Wassereinheit pro Sekunde. Das ist alles schön und gut, weil deine Bevölkerung 90 ist, damit jeder genug Wasser bekommt.
Nun entscheidet der Bürgermeister (= Sie), dass Sie ein großes Restaurant (= Browser) eröffnen wollen. Dieses Restaurant beherbergt mehrere Köche (= Browser-Tabs). Jeder Koch benötigt 1 Einheit Wasser pro Sekunde. Sie beginnen mit 10 Köchen, der Gesamtwasserverbrauch für die gesamte Nachbarschaft beträgt also 100 Einheiten Wasser, was immer noch alles in Ordnung ist.
Jetzt beginnt das lustige Zeug: Sie stellen einen anderen Koch in Ihr Restaurant ein, der den gesamten Wasserbedarf 101 ergibt, den Sie offensichtlich nicht haben. Du musst etwas tun.
Das Wassermanagement (= Kernel) hat 3 Möglichkeiten.
1. Die erste Möglichkeit besteht darin, den Dienst für die Häuser zu unterbrechen, die das Wasser in letzter Zeit nicht benutzt haben. Dies ist in Ordnung, aber wenn das getrennte Haus das Wasser wieder benutzen möchte, muss es den langwierigen Registrierungsprozess erneut durchlaufen. Das Management kann mehrere Häuser trennen, um mehr Wasserressourcen freizusetzen. Tatsächlich trennen sie alle Häuser, die in letzter Zeit kein Wasser verbraucht haben, und halten so immer eine gewisse Menge an freiem Wasser bereit.
Obwohl Ihre Stadt weiterhin funktioniert, ist der Nachteil, dass der Fortschritt zum Stillstand kommt. Die meiste Zeit verbringen Sie damit, auf das Wassermanagement zu warten, um Ihren Dienst wieder aufzunehmen.
Dies macht der Kernel mit den dateibasierten Seiten. Wenn Sie eine große ausführbare Datei (wie Chrome) ausführen, wird deren Datei in den Speicher kopiert. Wenn der Arbeitsspeicher knapp ist oder Teile vorhanden sind, auf die in letzter Zeit nicht zugegriffen wurde, kann der Kernel diese Teile löschen, da sie sowieso von der Festplatte geladen werden können. Wenn dies übermäßig getan wird, kommt Ihr Desktop zum Stillstand, da alles nur auf die Eingabe von Daten auf der Festplatte wartet. Beachten Sie, dass der Kernel auch viele der zuletzt verwendeten Seiten löscht, wenn Sie viel E / A ausführen. Aus diesem Grund dauert es eine Weile, bis Sie zu einer Hintergrund-App wechseln, nachdem Sie mehrere große Dateien wie DVD-Images kopiert haben.
Dies ist das nervigste Verhalten für mich, weil ich Hickups hasse und Sie keine Kontrolle darüber haben. Es wäre schön, es ausschalten zu können. Ich denke an etwas in der Art von
sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c
und dann könnten Sie vm_swappiness auf -1 setzen, um dies zu deaktivieren. Das hat in meinen kleinen Tests ganz gut geklappt, aber leider bin ich kein Kernel-Entwickler, also habe ich es niemandem geschickt (und offensichtlich ist die kleine Modifikation oben nicht vollständig).
2.Die Direktion könnte die Bitte des neuen Kochs um Wasser ablehnen. Das klingt zunächst nach einer guten Idee. Es gibt jedoch zwei Nachteile. Erstens gibt es Unternehmen, die viele Wasserabonnements beantragen, obwohl sie diese nicht nutzen. Ein möglicher Grund dafür besteht darin, den gesamten Aufwand zu vermeiden, mit der Wasserwirtschaft zu sprechen, wenn sie zusätzliches Wasser benötigt. Ihr Wasserverbrauch steigt und sinkt je nach Tageszeit. Im Fall des Restaurants benötigt das Unternehmen zum Beispiel mittags viel mehr Wasser als um Mitternacht. Sie fordern also alles mögliche Wasser an, das sie verwenden könnten, aber das verschwendet die Wasserzuteilung während Mitternacht. Das Problem ist, dass nicht alle Unternehmen ihre Spitzenauslastung richtig vorhersehen können und daher viel mehr verlangen, in der Hoffnung, dass sie sich nie mehr darum kümmern müssen.
Dies ist, was Java Virtual Machine tut: Es reserviert eine Menge Speicher beim Start und funktioniert dann von diesem. Standardmäßig reserviert der Kernel den Speicher nur, wenn Ihre Java-App ihn tatsächlich verwendet. Wenn Sie Overcommit deaktivieren, nimmt der Kernel die Reservierung jedoch ernst. Die Zuweisung ist nur dann erfolgreich, wenn tatsächlich die Ressourcen dafür vorhanden sind.
Bei diesem Ansatz gibt es jedoch ein anderes, schwerwiegenderes Problem. Angenommen, ein Unternehmen fordert jeden Tag eine einzelne Wassereinheit an (statt in Schritten von 10). Schließlich erreichen Sie einen Zustand, in dem Sie 0 freie Einheiten haben. Jetzt wird diese Firma nicht mehr in der Lage sein, mehr zuzuteilen. Das ist in Ordnung, wer kümmert sich schon um die großen Unternehmen? Das Problem ist jedoch, dass die kleinen Häuser auch kein Wasser mehr anfordern können! Sie werden nicht in der Lage sein, kleine öffentliche Bäder zu bauen, um den plötzlichen Zustrom von Touristen zu bewältigen. Sie können im nahe gelegenen Wald kein Notwasser für das Feuer bereitstellen.
In Bezug auf den Computer: In Situationen mit sehr wenig Arbeitsspeicher können Sie ohne Überbeanspruchung kein neues xterm öffnen, Sie können nicht in Ihren Computer sshen, Sie können kein neues Register öffnen, nach dem gesucht werden kann behebt. Mit anderen Worten: Durch Deaktivieren von Overcommit wird Ihr Desktop auch dann unbrauchbar, wenn der Arbeitsspeicher knapp wird.
3. Hier ist eine interessante Möglichkeit, das Problem zu lösen, wenn ein Unternehmen anfängt, zu viel Wasser zu verwenden. Das Wassermanagement sprengt es! Wörtlich: Es geht zum Restaurant, wirft Dynamit hinein und wartet, bis es explodiert. Dadurch wird der Wasserbedarf der Stadt sofort um ein Vielfaches gesenkt, sodass neue Menschen einziehen, öffentliche Badezimmer usw. geschaffen werden können. Als Bürgermeister können Sie das Restaurant in der Hoffnung wiederaufbauen, dass diesmal weniger Wasser benötigt wird. Zum Beispiel werden Sie die Leute anweisen, nicht in die Restaurants zu gehen, wenn sich bereits zu viele Personen darin befinden (z. B. werden weniger Browser-Registerkarten geöffnet).
Dies ist eigentlich das, was der Kernel macht, wenn ihm alle Optionen ausgehen und er Speicher benötigt: Er ruft den OOM-Killer auf. Es wählt eine große Anwendung aus (basierend auf vielen Heuristiken) und beendet sie, wodurch Speicherplatz frei wird, aber ein ansprechender Desktop beibehalten wird. Tatsächlich macht der Android-Kernel dies sogar noch aggressiver: Er beendet die am wenigsten genutzte App, wenn der Speicher knapp wird (im Vergleich zum Standard-Kernel, der dies nur als letzten Ausweg tut). Dies wird in Android als Viking Killer bezeichnet.
Ich denke, dies ist eine der einfachsten Lösungen für das Problem: Es ist nicht so, als hätten Sie mehr Optionen als dies. Warum sollten Sie nicht früher als später darüber hinwegkommen, oder? Das Problem ist, dass der Kernel manchmal ziemlich viel Arbeit leistet, um den OOM-Killer nicht aufzurufen. Das ist der Grund, warum Sie feststellen, dass Ihr Desktop sehr langsam ist und der Kernel nichts dagegen unternimmt. Aber zum Glück gibt es eine Option, den OOM-Killer selbst aufzurufen! Stellen Sie zunächst sicher, dass der Magic Sysrq-Schlüssel aktiviert ist (z. B. echo 1 | sudo tee
/proc/sys/kernel/sysrq
), und drücken Sie einfach Alt + SysRQ, Alt + F, wenn Sie das Gefühl haben, dass der Kernel fast voll ist.
OK, das ist alles schön, aber Sie möchten es ausprobieren? Die Situation mit wenig Speicher ist sehr einfach zu reproduzieren. Ich habe eine sehr einfache App dafür. Sie müssen es zweimal ausführen. Der erste Durchlauf bestimmt, wie viel freier Arbeitsspeicher Sie haben, der zweite Durchlauf schafft die Situation mit wenig Arbeitsspeicher. Beachten Sie, dass diese Methode davon ausgeht, dass Sie Swap deaktiviert haben (z sudo swapoff -a
. B. do a ). Code und Verwendung folgen:
// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int limit = 123456789;
if (argc >= 2) {
limit = atoi(argv[1]);
}
setbuf(stdout, NULL);
for (int i = 1; i <= limit; i++) {
memset(malloc(1 << 20), 1, 1 << 20);
printf("\rAllocated %5d MiB.", i);
}
sleep(10000);
return 0;
}
Und so verwenden Sie es:
$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed
Beim ersten Aufruf wurde festgestellt, dass 31.118 MB freier Arbeitsspeicher vorhanden sind. Also sagte ich der Anwendung, sie solle 31.110 MiB RAM zuweisen, damit der Kernel ihn nicht abbricht, sondern fast meinen gesamten Speicher aufzehrt. Mein System fror ein: Auch der Mauszeiger rührte sich nicht. Ich habe Alt + SysRQ, Alt + F gedrückt und es hat meinen EATMEM-Prozess beendet und das System wurde wiederhergestellt.
Auch wenn wir unsere Optionen behandelt haben, die in einer Situation mit wenig Arbeitsspeicher funktionieren, besteht der beste Ansatz (wie bei jeder anderen gefährlichen Situation) darin, dies überhaupt zu vermeiden. Dafür gibt es viele Möglichkeiten. Ein üblicher Weg, den ich gesehen habe, besteht darin, die fehlerhaften Anwendungen (wie Browser) in andere Container als den Rest des Systems zu verschieben. In diesem Fall kann der Browser keine Auswirkungen auf Ihren Desktop haben. Aber die Prävention selbst liegt außerhalb des Rahmens der Frage, deshalb werde ich nicht darüber schreiben.
TL; DR: Obwohl es derzeit keine Möglichkeit gibt, Paging vollständig zu vermeiden, können Sie einen vollständigen Systemstopp abmildern, indem Sie Overcommit deaktivieren. In Situationen mit wenig Arbeitsspeicher wird Ihr System jedoch weiterhin unbrauchbar sein, allerdings auf andere Weise. Unabhängig davon drücken Sie in einer Situation mit wenig Arbeitsspeicher Alt + SysRQ, Alt + f, um einen großen Prozess nach Wahl des Kernels abzubrechen. Ihr System sollte nach einigen Sekunden seine Reaktionsfähigkeit wiederherstellen. Dies setzt voraus, dass Sie den magischen sysrq-Schlüssel aktiviert haben (dies ist nicht die Standardeinstellung).