Diese Frage ist ziemlich lang, daher stelle ich die Fragen oben und gehe dann meine Methode durch, um zu den Fragen zu gelangen:
- Wurde (Busybox-basiert) rm nicht ausgeführt, weil nicht genügend zusammenhängender RAM vorhanden war?
- Wenn ja, gibt es eine einfache Methode zum Defragmentieren des DMA - ohne auf einen Systemneustart zurückzugreifen?
- 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:
- Wurde rm nicht ausgeführt, weil nicht genügend zusammenhängender RAM vorhanden war?
- Wenn ja, gibt es eine einfache Methode zum Defragmentieren des DMA - ohne auf einen Systemneustart zurückzugreifen?
- 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.
Antworten:
Zu Ihrer Frage 2 (Defragmentierung des Speichers) unter Angabe von https://www.kernel.org/doc/Documentation/sysctl/vm.txt :
Dies impliziert, dass der folgende Befehl (ausgeführt mit Root-Rechten und wenn die oben erwähnte Kernel-Option aktiviert war)
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 ...
quelle
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.
quelle