Interesuje mnie różnica między Highmem i Lowmem:
- Dlaczego istnieje takie zróżnicowanie?
- Co zyskujemy dzięki temu?
- Jakie funkcje ma każda z nich?
Interesuje mnie różnica między Highmem i Lowmem:
Odpowiedzi:
W architekturze 32-bitowej zakres przestrzeni adresowej dla adresowania pamięci RAM to:
0x00000000 - 0xffffffff
lub 4'294'967'295
(4 GB).
Jądro linuksa dzieli to 3/1 (może być również 2/2 lub 1/3 1 ) odpowiednio na przestrzeń użytkownika (wysoka pamięć) i przestrzeń jądra (mała pamięć).
Zakres przestrzeni użytkownika:
0x00000000 - 0xbfffffff
Każdy nowo spawnowany proces użytkownika otrzymuje adres (zakres) w tym obszarze. Procesy użytkownika są na ogół niezaufane i dlatego zabronione jest uzyskiwanie dostępu do przestrzeni jądra. Co więcej, są one uważane za niepilne, co do zasady, jądro próbuje odroczyć przydział pamięci dla tych procesów.
Zakres przestrzeni jądra:
0xc0000000 - 0xffffffff
Procesy jądra uzyskują tutaj swój adres (zakres). Jądro może uzyskać bezpośredni dostęp do 1 GB adresów (cóż, nie do pełnego 1 GB, zarezerwowano 128 MB na dostęp do wysokiej pamięci).
Procesy odradzające się w przestrzeni jądra są zaufane, pilne i przyjęte jako wolne od błędów, żądanie pamięci jest przetwarzane natychmiast.
Każdy proces jądra może również uzyskać dostęp do zakresu przestrzeni użytkownika, jeśli chce. Aby to osiągnąć, jądro odwzorowuje adres z przestrzeni użytkownika (pamięć wysoka) na przestrzeń jądra (pamięć mało), wspomniane powyżej 128 MB jest na to specjalnie zarezerwowane.
1 To, czy podział wynosi 3/1, 2/2, czy 1/3, zależy od CONFIG_VMSPLIT_...
opcji; prawdopodobnie możesz sprawdzić poniżej, /boot/config*
aby zobaczyć, która opcja została wybrana dla twojego jądra.
Pierwsze odniesienie, do którego należy się zwrócić, to sterowniki urządzeń Linux (dostępne zarówno online, jak i w formie książkowej), zwłaszcza rozdział 15, który zawiera sekcję na ten temat.
W idealnym świecie każdy element systemu byłby w stanie zmapować całą pamięć, do której kiedykolwiek miał dostęp. Dotyczy to procesów w systemie Linux i większości systemów operacyjnych: proces 32-bitowy może uzyskać dostęp tylko do mniej niż 2 ^ 32 bajtów pamięci wirtualnej (w rzeczywistości około 3 GB w typowej 32-bitowej architekturze Linux). Jądro staje się trudne, ponieważ musi być w stanie zmapować pełną pamięć procesu, którego wywołanie systemowe wykonuje, a także całą pamięć fizyczną i inne urządzenie sprzętowe odwzorowane w pamięci.
Więc kiedy 32-bitowe jądro musi zmapować więcej niż 4 GB pamięci, musi zostać skompilowane z obsługą wysokiej pamięci. Wysoka pamięć to pamięć, która nie jest na stałe mapowana w przestrzeni adresowej jądra. (Niska pamięć jest odwrotna: jest zawsze odwzorowywana, więc można uzyskać do niej dostęp w jądrze po prostu usuwając odwołanie ze wskaźnika).
Kiedy uzyskujesz dostęp do wysokiej pamięci z kodu jądra, musisz kmap
najpierw wywołać , aby uzyskać wskaźnik ze struktury danych strony ( struct page
). Wywoływanie kmap
działa niezależnie od tego, czy strona jest w pamięci wysokiej, czy niskiej. Jest też to, kmap_atomic
co dodało ograniczenia, ale jest bardziej wydajne na maszynach wieloprocesorowych, ponieważ wykorzystuje bardziej precyzyjne blokowanie. Wskaźnik uzyskany przez kmap
jest zasobem: zużywa przestrzeń adresową. Po zakończeniu musisz zadzwonić kunmap
(lub kunmap_atomic
), aby zwolnić ten zasób; wskaźnik nie jest już prawidłowy i nie można uzyskać dostępu do zawartości strony, dopóki nie zadzwonisz kmap
ponownie.
Dotyczy to jądra Linux; Nie jestem pewien, jak radzi sobie z tym jądro uniksowe.
Wysoka pamięć jest segmentem pamięci, który mogą adresować programy w przestrzeni użytkownika. Nie może dotknąć niskiej pamięci.
Niska pamięć to segment pamięci, który jądro Linux może rozwiązać bezpośrednio. Jeśli jądro musi uzyskać dostęp do High Memory, musi najpierw zmapować je we własnej przestrzeni adresowej.
Niedawno wprowadzono łatkę, która pozwala kontrolować, gdzie znajduje się segment. Kompromis polega na tym, że możesz zabrać pamięć adresowalną z przestrzeni użytkownika, aby jądro mogło mieć więcej pamięci, której nie musi mapować przed użyciem.
Dodatkowe zasoby:
HIGHMEM to zakres przestrzeni pamięci jądra, ale NIE jest to pamięć, do której masz dostęp, ale jest to miejsce, w którym umieszczasz to, do czego chcesz uzyskać dostęp.
Typowa 32-bitowa mapa pamięci wirtualnej systemu Linux wygląda następująco:
0x00000000-0xbfffffff: proces użytkownika (3 GB)
0xc0000000-0xffffffff: przestrzeń jądra (1 GB)
(Wektor specyficzny dla procesora i w ogóle są tutaj ignorowane).
Linux dzieli przestrzeń jądra 1 GB na 2 części, LOWMEM i HIGHMEM. Podział różni się w zależności od instalacji.
Jeśli instalacja wybierze, powiedzmy, 512 MB-512 MB dla memów LOW i HIGH, 512 MB LOWMEM (0xc0000000-0xdfffffff) jest statycznie odwzorowywany w czasie uruchamiania jądra; zwykle wykorzystuje się do tego tyle pierwszych bajtów pamięci fizycznej, że adresy wirtualne i fizyczne w tym zakresie mają stałe przesunięcie, powiedzmy, 0xc0000000.
Z drugiej strony ten ostatni 512 MB (HIGHMEM) nie ma mapowania statycznego (chociaż można pozostawić strony częściowo na stałe mapowane, ale należy to wyraźnie zrobić w kodzie sterownika). Zamiast tego strony są tutaj tymczasowo mapowane i niezmapowane, aby adresy wirtualne i fizyczne w tym zakresie nie miały spójnego mapowania. Typowe zastosowania HIGHMEM obejmują bufory danych jednorazowe.
Wiele osób twierdzi, że za mało pamięci dotyczy systemu operacyjnego. Jest to zwykle prawda, ale nie musi tak być. Wysoka pamięć i niska pamięć to tylko dwie części przestrzeni pamięci, ale w systemie Linux mała pamięć jest przeznaczona tylko na jądro, a wysoka pamięć na procesy użytkownika.
Zgodnie z „Książką dinozaurów (koncepcje systemu operacyjnego)” możemy umieścić system operacyjny w małej lub wysokiej pamięci. Głównym czynnikiem wpływającym na tę decyzję jest lokalizacja wektora przerwań. Ponieważ wektor przerwań często ma mało pamięci, programiści zwykle umieszczają również system operacyjny w małej ilości pamięci.