limit pamięci jądra Linux

12

Mam kłopotliwy problem. Mam bibliotekę, która używa sg do wykonywania niestandardowych CDB. Istnieje kilka systemów, które rutynowo mają problemy z alokacją pamięci w SG . Zwykle sterownik sg ma twardy limit około 4 MB, ale widzimy go w tych kilku systemach z żądaniami ~ 2,3 MB. Oznacza to, że CDB przygotowują się do alokacji na transfer 2,3 Mb. Nie powinno tu być żadnego problemu: 2.3 <4.0.

Teraz profil maszyny. Jest to 64-bitowy procesor, ale działa na 32-bitowym CentOS 6.0 (nie zbudowałem ich ani nie mam nic wspólnego z tą decyzją). Wersja jądra dla tej dystrybucji CentOS to 2.6.32. Mają 16 GB pamięci RAM.

Oto, jak wygląda użycie pamięci w systemie (ponieważ ponieważ ten błąd występuje podczas testów automatycznych, jeszcze nie sprawdziłem, czy odzwierciedla to stan, w którym to errno jest zwracane z sg ).

top - 00:54:46 up 5 days, 22:05,  1 user,  load average: 0.00, 0.01, 0.21
Tasks: 297 total,   1 running, 296 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  15888480k total,  9460408k used,  6428072k free,   258280k buffers
Swap:  4194296k total,        0k used,  4194296k free,  8497424k cached

Znalazłem ten artykuł z Linux Journal, który dotyczy alokacji pamięci w jądrze. Artykuł jest datowany, ale wydaje się, że dotyczy 2.6 (niektóre komentarze na temat autora na czele). W artykule wspomniano, że jądro jest ograniczone do około 1 GB pamięci (choć z tekstu nie jest całkowicie jasne, czy ten 1 GB dla fizycznych i wirtualnych lub ogółem). Zastanawiam się, czy jest to dokładne stwierdzenie dotyczące wersji 2.6.32. W końcu zastanawiam się, czy te systemy osiągają ten limit.

Chociaż tak naprawdę nie jest to odpowiedź na mój problem, zastanawiam się nad prawdziwością roszczenia dotyczącego wersji 2.6.32. Zatem jaki jest rzeczywisty limit pamięci dla jądra? Może to wymagać rozważenia przy rozwiązywaniu problemów. Wszelkie inne sugestie są mile widziane. Co sprawia, że ​​jest to tak zaskakujące, że systemy te są identyczne z wieloma innymi, które nie wykazują tego samego problemu.

Andrew Falanga
źródło

Odpowiedzi:

21

Limit 1 GiB dla pamięci jądra Linux w systemie 32-bitowym jest konsekwencją adresowania 32-bitowego i jest dość sztywny. Zmiana nie jest niemożliwa, ale istnieje z bardzo dobrego powodu; zmiana ma konsekwencje.

Przejdźmy do maszyny powrotnej do wczesnych lat 90., kiedy powstawał Linux. W tamtych czasach kłóciliśmy się o to, czy Linux mógłby działać w 2 MB pamięci RAM, czy naprawdę potrzebowałby 4 całych MiB . Oczywiście, wszystkie wysokiej klasy snoby szydziły z nas, z ich 16 potwornymi serwerami MiB.

Co ta zabawna mała winieta ma z tym wspólnego? W tym świecie łatwo jest podejmować decyzje dotyczące podziału przestrzeni adresowej 4 GiB uzyskanej z prostego adresowania 32-bitowego. Niektóre systemy operacyjne po prostu dzielą go na pół, traktując górny bit adresu jako „flagę jądra”: adresy od 0 do 2 31 -1 miały wyczyszczony górny bit i dotyczyły kodu przestrzeni użytkownika, a adresy od 2 31 do 2 32 - 1 miałem ustawiony najwyższy bit i były dla jądra. Możesz po prostu spojrzeć na adres i powiedzieć: 0x80000000 i więcej, jest to przestrzeń jądra, w przeciwnym razie jest to przestrzeń użytkownika.

Gdy rozmiary pamięci komputera gwałtownie wzrosły do ​​tego limitu pamięci 4 GiB, ten prosty podział 2/2 zaczął stanowić problem. Zarówno przestrzeń użytkownika, jak i przestrzeń jądra miały dobre zdanie na temat dużej ilości pamięci RAM, ale ponieważ naszym celem jest posiadanie komputera na ogół do uruchamiania programów użytkownika, a nie jądra, systemy operacyjne zaczęły bawić się z podziałem użytkownik / jądro. Podział 3/1 jest powszechnym kompromisem.

Jeśli chodzi o twoje pytanie na temat fizycznego vs wirtualnego, tak naprawdę nie ma znaczenia. Technicznie rzecz biorąc, jest to limit pamięci wirtualnej, ale to tylko dlatego, że Linux jest systemem operacyjnym opartym na VM. Zainstalowanie 32 GiB fizycznej pamięci RAM niczego nie zmieni, ani nie pomoże swaponpartycji wymiany 32 GiB. Bez względu na to, co robisz, 32-bitowe jądro Linuksa nigdy nie będzie w stanie obsłużyć więcej niż 4 GiB jednocześnie.

(Tak, wiem o PAE . Teraz, gdy 64-bitowe systemy operacyjne w końcu przejmują kontrolę, mam nadzieję, że możemy zacząć zapominać o tym paskudnym włamaniu. Nie sądzę, by to mogło ci w tym pomóc.)

Najważniejsze jest to, że jeśli napotykasz limit VM 1 jądra GiB, możesz odbudować jądro z podziałem 2/2, ale to bezpośrednio wpływa na programy kosmiczne użytkownika.

Wersja 64-bitowa jest naprawdę właściwą odpowiedzią.

Warren Young
źródło
1
Dzięki. Ten opis jest świetny. Natknąłem się na podział 2/2 powszechnie używany w systemie Windows. W tym czasie dowiedziałem się, że Linux używa podziału 3/1. Żałuję, że nie pomyślałem o tym podczas czytania artykułu, myślę, że połączyłbym kropki. Więc ... to brzmi, jakbym musiał o tym pamiętać. Prawdopodobnie nie jest daleko poza zasięgiem, aby sądzić, że te systemy przekraczają granice, biorąc pod uwagę charakter testów. Najważniejsze pytanie brzmi: dlaczego inne systemy również tego nie doświadczają. Dzięki jeszcze raz.
Andrew Falanga
1
@AndrewFalanga: W rzeczywistości nowoczesny system Windows również używa rozmytego podziału 3/1 .
Warren Young,
1
Niektórzy z nas byli w stanie połączyć pamięć z trzech różnych maszyn odziedziczonych po SSC, aby uzyskać serwer 12 MB. Tak dużo pamięci możemy zrobić coś, co chcieliśmy ...
dmckee --- ex-moderator kotek
3
„Tak, wiem o modelu pamięci segmentowej x86 . Teraz, gdy 32-bitowe systemy operacyjne wreszcie przejmują, mam nadzieję, że możemy zacząć zapominać o tym okropnym włamaniu.”
CVn
Podwojenie między 32- i 64-bitowymi bitami jest dwukrotnie większe niż między 16- i 32-bitowymi, co podwaja czas, jaki musimy odłożyć na takie hacki, przy czym wszystkie pozostałe są równe. Ale wszystko inne nie jest równe, co z zachodem prawa Moore'a. Mamy dwie dekady z 32-bitowego przetwarzania x86. Możemy uzyskać wieki z wersji 64-bitowej. Jednoprzebiegowy odczyt 2⁶⁴ bajtów pamięci RAM przy dzisiejszych przepustowościach pamięci DRAM zająłby około 30 lat . Skąd nastąpi zwiększenie przepustowości, aby umożliwić nam osiągnięcie 64-bitowego limitu?
Warren Young,
2

Chcę dodać trochę do doskonałej odpowiedzi Warrena Younga , ponieważ rzeczy są w rzeczywistości gorsze, niż pisze.

Przestrzeń adresowa jądra 1 GB jest dalej podzielona na dwie części. 128 MB dla vmalloci 896 MB dla lowmem. Nieważne, co to właściwie oznacza. Podczas przydzielania pamięci kod jądra musi wybrać, który z nich chce. Nie można po prostu uzyskać pamięci z puli, która ma wolne miejsce.

Jeśli wybierzesz vmalloc, masz ograniczenie do 128 MB. Teraz 1 GB nie wygląda tak źle ...

Jeśli wybierzesz lowmem, jesteś ograniczony do 896 MB. Nie tak daleko od 1 GB, ale w tym przypadku wszystkie alokacje są zaokrąglane w górę do następnej potęgi 2. Tak więc alokacja 2,3 MB w rzeczywistości zużywa 4 MB. Ponadto nie można przydzielić więcej niż 4 MB na jedno połączenie podczas korzystania lowmem.

Wersja 64-bitowa jest naprawdę właściwą odpowiedzią.

ugoren
źródło
Mam pytanie związane z twoją odpowiedzią. Czy dla tej przestrzeni pamięci o nazwie lowmem pochodzi pamięć z wywołań takich jak kmalloc i kzmalloc?
Andrew Falanga,
@AndrewFalanga, tak, te funkcje używają lowmem.
ugoren