RAM / OOM-Fehler defragmentieren

11

Diese Frage ist ziemlich lang, daher stelle ich die Fragen oben und gehe dann meine Methode durch, um zu den Fragen zu gelangen:

  1. Wurde (Busybox-basiert) rm nicht ausgeführt, weil nicht genügend zusammenhängender RAM vorhanden war?
  2. Wenn ja, gibt es eine einfache Methode zum Defragmentieren des DMA - ohne auf einen Systemneustart zurückzugreifen?
  3. Wenn nicht, was hat es verursacht? Wie kann ich verhindern, dass dies in Zukunft geschieht?

Nachdem unser Testsystem in den letzten Tagen ziemlich intensiv gelaufen war, habe ich mich in das System eingemischt und die Testergebnisse überprüft. Als ich einige Daten löschen wollte, gab das System die Befehlszeile zurück (als ob der Befehl korrekt ausgeführt worden wäre). Als ich das Verzeichnis auf andere Ergebnisse überprüfte, sah ich, dass die Datei noch vorhanden war (mit ls).

Danach bemerkte ich, dass immer mehr meiner Shell-Befehle nicht wie erwartet ausgeführt wurden.

Ich beginne mit einer Ausgabe von dmesg, nachdem rm nicht korrekt ausgeführt wurde:

Die Zuordnung der Länge 61440 aus dem Prozess 6821 (rm) ist fehlgeschlagen

DMA pro CPU:

CPU 0: hi: 0, btch: 1 usd: 0

Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 nicht vorhersehbar: 6 schmutzig: 0 Rückschreibung: 0 instabil: 0 frei: 821 Platte: 353 zugeordnet: 0 Seiten: 0 Sprungkraft: 0

DMA frei: 3284kB min: 360kB niedrig: 448kB hoch: 540kB active_anon: 0kB inactive_anon: 0kB active_file: 4kB inactive_file: 0kB nicht vorhersehbar: 24kB vorhanden: 8128kB pages_scanned: 0 all_unreclaimable? Nein

lowmem_reserve []: 0 0 0

DMA: 31 * 4 kB 47 * 8 kB 42 * 16 kB 64 * 32 kB 1 * 64 kB 0 * 128 kB 0 * 256 kB 0 * 512 kB 0 * 1024 kB 0 * 2048 kB 0 * 4096 kB = 3284 kB

Insgesamt 14 Seitencache-Seiten

RAM für Prozessdaten kann nicht zugeordnet werden, Fehler Nr. 12

Anfangs dachte ich, ich könnte das Programm nicht im größten Teil des zusammenhängenden Speichers ausführen. Das heißt, der DMA war zu fragmentiert und ich müsste einen Weg finden, das System dazu zu bringen, den Speicher zu defragmentieren.

Dann führte ich eine schnelle Mathematik- / Vernunftprüfung durch und stellte fest, dass das Programm in dem einzigen zusammenhängenden 64-KB-Speicherplatz ausgeführt werden sollte. Rm forderte 61440 Bytes (60 kB) an.

Ich habe eine gute alte "manuelle Defragmentierung" durchgeführt und das System neu gestartet. Beim Neustart des Systems habe ich / proc / buddyinfo ausgegeben:

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

Was ich vermute Karte zu:

  • 2 x 4 kB
  • 8 x 8 kB
  • 3 x 16 kB
  • 12 x 32 kB
  • 1 x 128 kB
  • 1 x 512 kB

Wenn man jedoch die obige Werteliste summiert , stimmt sie nicht mit der Ausgabe von / proc / meminfo überein :

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

Zusammenfassend sind meine Fragen:

  1. Wurde rm nicht ausgeführt, weil nicht genügend zusammenhängender RAM vorhanden war?
  2. Wenn ja, gibt es eine einfache Methode zum Defragmentieren des DMA - ohne auf einen Systemneustart zurückzugreifen?
  3. Wenn nicht, was hat es verursacht? Wie kann ich verhindern, dass dies in Zukunft geschieht?

Ich verwende Lantronix XPort Pro (8 MB, Linux OS) mit uClinux Version 2.6.30. Die verwendete Schale ist still.

OldTinfoil
quelle
Kleiner Punkt: Sie haben 1 x 2048 kB aus Ihrer Liste der Speicherblöcke weggelassen. Wenn Sie dies einbeziehen, beträgt die Summe 3192 kB, was sehr nahe an den in / proc / meminfo aufgeführten 3164 kB liegt.
Alex Selby

Antworten:

11

Zu Ihrer Frage 2 (Defragmentierung des Speichers) unter Angabe von https://www.kernel.org/doc/Documentation/sysctl/vm.txt :

compact_memory

Nur verfügbar, wenn CONFIG_COMPACTION festgelegt ist. Wenn 1 in die Datei geschrieben wird, werden alle Zonen so komprimiert, dass nach Möglichkeit freier Speicher in zusammenhängenden Blöcken verfügbar ist. Dies kann beispielsweise bei der Zuweisung großer Seiten wichtig sein, obwohl Prozesse den Speicher bei Bedarf auch direkt komprimieren.

Dies impliziert, dass der folgende Befehl (ausgeführt mit Root-Rechten und wenn die oben erwähnte Kernel-Option aktiviert war)

echo 1 > /proc/sys/vm/compact_memory

sollte den Kernel anweisen, zu versuchen, den Speicher so weit wie möglich zu defragmentieren. Beachten Sie, dass z. B. bei einigen RHEL6-Versionen der Kernel abstürzen kann ...

Andre Holzner
quelle
1
Vielen Dank, dass Sie sich die Zeit genommen haben, eine alte Frage zu kommentieren!
OldTinfoil
7

Es hat ein bisschen gedauert, aber ich dachte, ich würde die Beantwortung so lange unterbrechen, bis ich Antworten auf alle drei meiner Unterfragen hatte.

Bevor ich jedoch anfange, möchte ich erwähnen, dass der richtige Begriff für das "Entfragmentieren" des Arbeitsspeichers als "Verdichten" des Arbeitsspeichers bezeichnet wird.

1. Wurde rm nicht ausgeführt, weil nicht genügend zusammenhängender RAM vorhanden war?

Ich war in meiner Schlussfolgerung richtig - rm wurde nicht ausgeführt, weil nicht genügend zusammenhängender RAM vorhanden war. Das System hatte RAM erworben und fragmentiert, wodurch es nicht mehr zurückgefordert werden konnte.

2. Wenn ja, gibt es eine einfache Methode zum Defragmentieren des DMA - ohne auf einen Systemneustart zurückzugreifen?

Es stellt sich heraus, dass es keine Möglichkeit gibt, den Speicher zu komprimieren, außer das eingebettete System neu zu starten. Bei einem System ohne MMU ist Prävention der Name des Spiels.

Ein Teil von mir überlegt, ob es möglich ist, den Linux-Kernel zu hacken, um die MMU in Software zu emulieren. Ich denke, wenn es möglich wäre, hätte es schon jemand getan. Ich kann mir nicht vorstellen, dass es ein völlig neues Konzept ist;)

3. Wie kann ich verhindern, dass dies in Zukunft geschieht?

Für dieses Projekt habe ich cron verwendet, um das Programm jedes Mal manuell zu starten, wenn es benötigt wurde. Eine viel bessere Möglichkeit, dies zu tun, besteht darin, das Programm beim Start aufzurufen und das Programm dann in den Ruhezustand zu zwingen, bis es benötigt wird. Auf diese Weise muss der Speicher nicht bei jeder Verwendung zugewiesen werden. Dadurch wird die Fragmentierung verringert.

Bei der ersten Iteration des Projekts haben wir uns auf meine Shell-Skriptaufrufe verlassen, um kritische Funktionen (wie z. B. rm) auszuführen. Wir haben nicht die Notwendigkeit gesehen, das Rad neu zu erfinden, wenn wir es nicht mussten.

Ich würde jedoch empfehlen, die Shell für ein System ohne MMU nach Möglichkeit zu vermeiden -

( Frage , was passiert, wenn Sie ausführen ls -la /path/to/directory/ | grep file-i-seek?)

( Antwort : Es wird ein neuer Unterprozess gestartet.)

Wenn Sie einige der Kernfunktionen des Shell-Skripts in Ihrem C-Programm implementieren müssen, empfehlen wir Ihnen, den in BusyBox verwendeten Quellcode zu überprüfen . Möglicherweise verwenden Sie C in Ihrem eingebetteten System.

OldTinfoil
quelle
Vielen Dank, dass Sie sich die Zeit genommen haben, zurück zu kommen und Ihre Ergebnisse zu teilen.
Caleb
3
[Mir ist klar, dass dies alt ist] Das Emulieren einer MMU ist schwierig ... Ohne eine MMU verwendet jedes Programm direkt die physischen Adressen, wie sie auf dem Speicherbus erscheinen. Sie könnten einen emulieren, müssten aber jeden Speicherzugriff abfangen (genau wie eine tatsächliche MMU). Leistung wäre schrecklich. Alternativ können Sie indirekte Zeiger verwenden (wie es Mac OS Classic getan hat und sie "Handles" nennt), aber dann haben Sie eine völlig schwierige API und eine sehr schwierige angesichts der Prävention (Mac OS Classic verwendet kooperatives Multitasking). .
Derobert
Vielen Dank, dass Sie zurückgekommen sind und sich die Zeit genommen haben, diese Antwort zu schreiben. Ich wusste nicht, dass MacOS classic das tut.
OldTinfoil