@ hiro, masz na myśli, że „HIGHMEM” to „wirtualny adres jądra”, jak opisano w ldd3. Zgadzam się z Tobą. jest mylące, ldd3 zdefiniował „LOWMEM” „HIGHMEM”, zdefiniował również „adres wirtualny jądra” „adres logiczny jądra”. są takie same, ale mają inną nazwę. to jest „piękno” oprogramowania, tak bardzo zależy od języka opisu.
steve,
Odpowiedzi:
69
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.
To jest stare i nie jestem pewien, czy tu jesteś. Ale chcę zapytać o jedno: zarezerwowane 128 MB miejsca w jądrze (dla dostępu do wysokiej pamięci), czy to wszystkie odniesienia do obszaru pamięci użytkownika? Tak więc proces jądra może uzyskać dostęp do dowolnej przestrzeni użytkownika, odwołując się do tego obszaru, prawda?
Amumu,
1
Dlaczego zawsze jest w 1/4? To znaczy, dlaczego nie można go podzielić na 5/1 czy coś takiego?
mgalgs
Co dokładnie oznacza tutaj „bezpośredni dostęp”? Mam na myśli, czy do samego jądra nie można uzyskać dostępu poprzez mechanizm pamięci wirtualnej?
telenn
1
Uważam, że to, co mówisz o wysokiej / niskiej pamięci jest błędne: uważam, że w czystym systemie 32-bitowym jądro może uzyskać dostęp do pełnego 3 GB przestrzeni użytkownika bezpośrednio (jądro może uzyskać dostęp do przestrzeni jądra i przestrzeni użytkownika). Jednak gdy masz jądro PAE, sprawy stają się bardziej złożone, teraz masz więcej niż 3 GB pamięci RAM, każdy proces może wynosić 3 GB i nie możesz uzyskać bezpośredniego dostępu do całej przestrzeni użytkownika. To tutaj pojawia się wysoka pamięć i 128 MB pamięci w przestrzeni jądra. Z 64-bitowym jądrem znów staje się prostsze, bez wysokich ludzi, ponieważ cała przestrzeń użytkownika jest dostępna z jądra.
ctrl-alt-delor
2
@mgalgs ¼, 2/4 i ¾ to tylko zestaw domyślnych opcji, które zostały ujawnione. Od 2007 roku można również wybrać 5/16 i 15/32. Jeśli wiesz, jak edytować linię #define, możesz wybrać prawie dowolny podział.
jørgensen
28
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 kmapnajpierw wywołać , aby uzyskać wskaźnik ze struktury danych strony ( struct page). Wywoływanie kmapdziała niezależnie od tego, czy strona jest w pamięci wysokiej, czy niskiej. Jest też to, kmap_atomicco dodało ograniczenia, ale jest bardziej wydajne na maszynach wieloprocesorowych, ponieważ wykorzystuje bardziej precyzyjne blokowanie. Wskaźnik uzyskany przez kmapjest 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 kmapponownie.
Dzięki Gilles za odpowiedź .. Ale wciąż nie jestem w stanie uzyskać całej koncepcji. Czy mógłbyś być nieco prostszy bez ograniczania zawartych w nim informacji?
Sen
17
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.
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.
Odpowiedzi:
W architekturze 32-bitowej zakres przestrzeni adresowej dla adresowania pamięci RAM to:
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:
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:
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.źródło
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ływaniekmap
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 przezkmap
jest zasobem: zużywa przestrzeń adresową. Po zakończeniu musisz zadzwonićkunmap
(lubkunmap_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 zadzwoniszkmap
ponownie.źródło
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:
źródło
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.
źródło
O ile pamiętam, „High Memory” jest używane dla przestrzeni aplikacji i „Low Memory” dla jądra.
Zaletą jest to, że aplikacje (przestrzeń użytkownika) nie mają dostępu do pamięci miejsca jądra.
źródło
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.
źródło