To pytanie jest dość długie, więc zadam pytania u góry, a następnie przejdę do mojej metody dochodzenia do pytań:
- Czy rm (oparty na Busybox) nie wykonał się, ponieważ nie było wystarczającej ilości ciągłej pamięci RAM?
- Jeśli tak, to czy istnieje lekka metoda defragmentacji DMA - bez uciekania się do restartu systemu?
- Jeśli nie, co go spowodowało? Jak mogę temu zapobiec w przyszłości?
Po tym, jak nasz system testowy działał dość intensywnie przez ostatnie kilka dni - telnet połączyłem się z systemem i sprawdziłem wyniki testu. Kiedy przyszedłem usunąć niektóre dane, system zwrócił wiersz poleceń (tak jakby polecenie wykonało się poprawnie). Kiedy przyszedłem sprawdzić katalog pod kątem innego zestawu wyników, zobaczyłem, że plik nadal istnieje (używając ls).
Po tym zauważyłem, że coraz więcej moich poleceń powłoki nie działa zgodnie z oczekiwaniami.
Zacznę od wyjścia z dmesg po tym, jak rm nie wykonał poprawnie:
Przydział długości 61440 z procesu 6821 (rm) nie powiódł się
DMA na jednostkę centralną:
CPU 0: hi: 0, btch: 1 usd: 0
Aktywny_anon: 0 Aktywny_plik: 1 Nieaktywny_anon: 0 Nieaktywny_plik: 0 Niewykrywalny: 6 Brudny: 0 Zapis zwrotny: 0 Niestabilny: 0 Wolny: 821 Płyta: 353 Odwzorowany: 0 Pagetable: 0 Odbicie: 0
DMA wolny: 3284kB min: 360kB niski: 448kB wysoki: 540kB aktywny_anon: 0kB nieaktywny_anon: 0kB aktywny_plik: 4kB nieaktywny_plik: 0kB nieunikniony: 24kB obecny: 8128kB skanowany stron: 0 all_creclaimable? Nie
lowmem_reserve []: 0 0 0
DMA: 31 * 4kB 47 * 8kB 42 * 16kB 64 * 32kB 1 * 64kB 0 * 128kB 0 * 256kB 0 * 512kB 0 * 1024kB 0 * 2048kB 0 * 4096kB = 3284kB
14 wszystkich stron pagecache
Nie można przydzielić pamięci RAM na dane procesowe, errno 12
Początkowo myślałem, że nie jestem w stanie uruchomić programu w największej części ciągłej pamięci. To znaczy, że DMA był zbyt rozdrobniony i musiałbym znaleźć sposób na zmusienie systemu do defragmentacji pamięci.
Potem zrobiłem szybką kontrolę matematyki / rozsądku i zdałem sobie sprawę, że program powinien być w stanie działać w jedynym ciągłym gnieździe pamięci 64kB. Rm zażądał 61440 bajtów (60 kB).
Zrobiłem starą dobrą „ręczną defragmentację” i ponownie uruchomiłem system. Po ponownym uruchomieniu systemu wyprowadzam / proc / buddyinfo:
Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0
Podejrzewam, że mapa do:
- 2 x 4 kB
- 8 x 8 kB
- 3 x 16 kB
- 12 x 32 kB
- 1 x 128 kB
- 1 x 512 kB
Ale jeśli sumuje się powyższą listę wartości, nie zgadza się ona z danymi wyjściowymi / proc / meminfo :
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
Podsumowując, moje pytania to:
- Czy polecenie rm nie zostało wykonane, ponieważ nie było wystarczającej ilości ciągłej pamięci RAM?
- Jeśli tak, to czy istnieje lekka metoda defragmentacji DMA - bez uciekania się do restartu systemu?
- Jeśli nie, co go spowodowało? Jak mogę temu zapobiec w przyszłości?
Korzystam z Lantronix XPort Pro (8 MB, Linux OS) z systemem uClinux w wersji 2.6.30. Używana powłoka jest cicha.
Odpowiedzi:
Na twoje pytanie 2 (defragmentacja pamięci), cytowanie z https://www.kernel.org/doc/Documentation/sysctl/vm.txt :
oznacza to, że następująca komenda (wykonywana z uprawnieniami roota i jeśli włączona została wspomniana powyżej opcja jądra)
powinien poinformować jądro, aby próbowało jak najbardziej defragmentować pamięć. Uwaga: np. W niektórych wersjach RHEL6 może to spowodować awarię jądra ...
źródło
Zajęło to trochę czasu, ale pomyślałem, że wstrzymam się od odpowiedzi, dopóki nie otrzymam odpowiedzi na wszystkie 3 moje pytania cząstkowe.
Zanim zacznę, wspomnę, że poprawne określenie „rozpakowywania” pamięci roboczej odnosi się do „pracy kompaktowej”.
1. Czy rm nie wykonał się, ponieważ nie było wystarczającej ilości ciągłej pamięci RAM?
Mój wniosek był poprawny - rm nie wykonał się, ponieważ nie było wystarczającej ciągłej pamięci RAM. System pozyskiwał pamięć RAM i dzielił ją na fragmenty, przez co nie można było jej odzyskać.
2. Jeśli tak, to czy istnieje lekka metoda defragmentacji DMA - bez uciekania się do restartu systemu?
Okazuje się, że nie ma sposobu na kompaktowanie pamięci, poza ponownym uruchomieniem systemu osadzonego. W przypadku systemu bez MMU zapobieganie to nazwa gry.
Część mnie zastanawia się, czy można zhakować jądro Linuksa, aby emulować MMU w oprogramowaniu. Myślę, że gdyby to było możliwe, ktoś już by to zrobił. Nie mogę sobie wyobrazić, że to zupełnie nowa koncepcja;)
3. Jak mogę temu zapobiec w przyszłości?
W tym projekcie korzystałem z crona, aby ręcznie inicjować program za każdym razem, gdy był wymagany. Znacznie lepszym sposobem na to jest wywołanie programu przy uruchamianiu, a następnie zmusienie programu do uśpienia, aż będzie to konieczne. W ten sposób pamięć nie musi być przydzielana przy każdym użyciu. W ten sposób zmniejsza się fragmentację.
Podczas pierwszej iteracji projektu polegaliśmy na moich wywołaniach skryptów powłoki do wykonywania funkcji krytycznych (takich jak rm). Nie widzieliśmy potrzeby ponownego wynalezienia koła, jeśli nie byłoby takiej potrzeby.
Zalecam jednak unikanie powłoki tam, gdzie to możliwe, w przypadku systemu bez MMU -
( Pytanie , co się stanie, jeśli wykonasz
ls -la /path/to/directory/ | grep file-i-seek
?)( Odpowiedź : uruchamia nowy podproces)
Jeśli potrzebujesz zaimplementować niektóre podstawowe funkcje skryptu powłoki w swoim programie C, polecam sprawdzenie kodu źródłowego używanego w BusyBox . Prawdopodobnie będziesz używać C we wbudowanym systemie.
źródło