Rozumiem, dlaczego jesteś zdezorientowany. Schemat jest nieco mylący i może być niepoprawny.
Po pierwsze, zastanówmy się, dlaczego jądro potrzebuje alokatora pamięci poniżej poziomu stron. To prawdopodobnie już rzeczy, które w większości wiesz, ale przejdę przez to dla kompletności.
Strony są typową „jednostką” operacji pamięci. Gdy aplikacja w przestrzeni użytkownika przydziela pamięć lub mapuje pamięć pliku lub coś w tym rodzaju, zwykle otrzymuje wielokrotność rozmiaru strony komputera. Istnieją pewne wyjątki; Windows używa 64k jako jednostki alokacji pamięci wirtualnej bez względu na rozmiar strony procesora. Niemniej jednak pomyślmy o tym w ten sposób.
W nowoczesnym CPU, jeśli chodzi o kod przestrzeni użytkownika, ma płaską przestrzeń adresową. Jest to złudzenie zapewnione przez system pamięci wirtualnej. System operacyjny zapewnia strony z dowolnego miejsca w pamięci RAM (lub w ogóle nie w pamięci RAM, w przypadku pamięci zamienionej lub plików mapowanych w pamięci) i mapuje je na ciągłą wirtualną przestrzeń adresową.
Chodzi o to, że oprócz kilku specjalnych przypadków dla samego systemu operacyjnego (być może buforów DMA, może niektórych specjalnych struktur danych skonfigurowanych w czasie uruchamiania, oh i samego obrazu jądra), jądro systemu operacyjnego prawdopodobnie nigdy nie musi zarządzaj dowolnym blokiem pamięci RAM większym niż strona. Upraszcza to ogromnie, ponieważ oznacza to, że jeśli chodzi o strony, każda alokacja i dezalokacja mają ten sam rozmiar. Skutecznie eliminuje również fragmentację zewnętrzną na poziomie makro.
Jednak jądra muszą także implementować niektóre własne struktury danych, a do tego potrzebują innego rodzaju alokatora pamięci. Te struktury danych zwykle można traktować jako zbiór pojedynczych obiektów (np. Obiekt może być „wątkiem” lub „muteksem”). Rozmiar tych obiektów jest zwykle znacznie mniejszy niż rozmiar strony.
Na przykład obiekt reprezentujący poświadczenia bezpieczeństwa procesu (powiedzmy identyfikator użytkownika i identyfikator grupy w POSIX, powiedzmy) może mieć tylko około 16 bajtów, podczas gdy „proces” lub „wątek” może mieć maksymalnie Rozmiar 1kb. Najwyraźniej nie chcesz używać całej strony dla tych małych rekordów, więc pomysł polega na wdrożeniu alokatora na górze stron.
System alokacji niższego poziomu musi spełniać wiele takich samych problemów jak alokator na poziomie strony: musi być dość szybki (w tym w systemach wielordzeniowych), aby zminimalizować fragmentację i tak dalej. Ale co ważniejsze, powinna być dostrajalna i konfigurowalna w zależności od rodzaju przechowywanej struktury danych.
Niektóre struktury danych są z natury „podobne do pamięci podręcznej”. Na przykład wiele systemów operacyjnych utrzymuje pamięć podręczną nazw ścieżek do obiektów systemu plików, aby uniknąć długich łańcuchów wyszukiwania katalogów (zwanych „pamięcią podręczną nazw” lub „pamięcią podręczną nazw” w systemie Unix-speak). Te obiekty są potrzebne tylko do wydajności, a nie do poprawności, więc możesz (teoretycznie) po prostu zapomnieć całą stronę pełną wpisów, jeśli pamięć jest wolna i musisz szybko zwolnić ramkę strony.
Inne struktury danych mogą zostać zamienione na dysk, jeśli pamięć jest napięta i wkrótce nie będziesz ich potrzebować. Ale nie chcesz tego robić ze strukturami danych, które kontrolują wymianę lub system pamięci wirtualnej!
Niektóre struktury danych mogą być przenoszone w pamięci bez żadnych kar (np. Jeśli nikt nie odnosi się do nich wskaźnikiem), więc mogą się „kompaktować”, aby w razie potrzeby uniknąć fragmentacji.
Główną ideą alokatora płyt jest to, że strona powinna przechowywać tylko struktury danych tego samego „typu”. To zaznacza wszystkie pola: każdy obiekt na stronie ma ten sam rozmiar, więc nie występuje fragmentacja zewnętrzna. Obiekty tego samego „typu” mają te same wymagania wydajnościowe i tę samą semantykę.
Nawiasem mówiąc, jest to podobna historia z alokacją. W przypadku niektórych typów obiektów prawdopodobnie dobrze jest poczekać, jeśli nie ma natychmiast dostępnej pamięci do przydzielenia tego obiektu. Obiekt reprezentujący otwarty plik może być jednym z przykładów; otwarcie pliku jest w najlepszym przypadku kosztowną operacją, więc dłuższe oczekiwanie nie zaszkodzi tak bardzo.
W przypadku innych typów obiektów (np. Obiektu reprezentującego zdarzenie w czasie rzeczywistym, które musi nastąpić za jakiś czas), naprawdę nie chcesz czekać. Dlatego sensowne jest, aby niektóre typy obiektów nadmiernie przydzielały (powiedzmy, że ma kilka wolnych stron w rezerwie), aby żądania mogły zostać spełnione bez czekania.
Zasadniczo robisz to, aby każdy typ obiektu miał własny alokator, który można skonfigurować na potrzeby tego obiektu. Te alokatory dla poszczególnych obiektów są myląco nazywane „pamięciami podręcznymi”. Przydzielasz jedną pamięć podręczną dla każdego typu obiektu. (Tak, zazwyczaj implementuje się także „pamięć podręczną pamięci podręcznej”). Każda pamięć podręczna przechowuje tylko obiekty tego samego typu (np. Tylko struktury wątków lub tylko struktury przestrzeni adresowej).
Z kolei każda pamięć podręczna zarządza „płytami”. Płyta jest ramką strony, która zawiera tablicę obiektów tego samego typu. Płyty mogą być „pełne” (wszystkie obiekty w użyciu), „puste” (brak obiektów w użyciu) lub „częściowe” (niektóre obiekty w użyciu).
Częściowe płyty są prawdopodobnie najciekawsze, ponieważ program przydzielający płyty utrzymuje bezpłatną listę dla każdej płyty częściowej. (Pełne płyty i puste płyty nie potrzebują wolnej listy.) Przedmioty są najpierw przydzielane z płyt częściowych (i prawdopodobnie z „najbardziej pełnych” płyt częściowych), aby uniknąć przydzielania niepotrzebnych stron.
Zaletą alokacji płyt jest to, że wszystkie opcje strategii alokacji (a także semantyka pamięci) mogą być dostrojone dla każdego rodzaju obiektu. Niektóre pamięci podręczne mogą zachować pulę pustych płyt, a inne nie. Niektóre mogą być zamienione na pamięć dodatkową, a inne nie.
Linux ma trzy różne rodzaje alokatora płyt, w zależności od tego, czy potrzebujesz kompaktowości, łatwości obsługi pamięci podręcznej, czy surowej prędkości. Kilka lat temu odbyła się na ten temat dobra prezentacja, która dobrze wyjaśnia kompromisy.
Narzędzie do dzielenia płyt Solaris (szczegółowe informacje znajdują się w dokumencie ) zawiera jeszcze kilka szczegółów, które pozwalają uzyskać jeszcze większą wydajność. Na początek w systemie Solaris wszystko odbywa się z alokacją płyty, w tym alokacją ramek strony. (Jest to rozwiązanie Solaris do alokacji obiektów, które są większe niż połowa strony.) Zarządza mniejszymi obiektami poprzez zagnieżdżanie alokatorów płyt w przestrzeni przydzielonej płytom.
Niektóre obiekty w Solarisie wymagają skomplikowanej i kosztownej budowy i zniszczenia (np. Obiekty z blokadą jądra), więc mogą być „częściowo darmowe” (tj. Zbudowane, ale nieprzydzielone). Solaris optymalizuje również alokację wolnych płyt poprzez utrzymywanie wolnych list na procesor, zapewniając, że niektóre operacje są całkowicie wolne od oczekiwania.
W celu obsługi alokacji ogólnego przeznaczenia (np. Dla tablic, których rozmiar nie jest znany w czasie kompilacji), większość systemów operacyjnych typu makrokernel ma również pamięci podręczne, które reprezentują rozmiary obiektów, a nie typy obiektów . Na przykład FreeBSD utrzymuje pamięci podręczne dla nieznanych obiektów, których rozmiary to moc 2 bajtów, od 4 do 256.
Mam nadzieję, że zobaczysz, że alokacja płyt jest bardzo elastyczną strukturą, którą można dostosować do potrzeb różnego rodzaju danych. Nie konkuruje ze stronicowaniem, ale uzupełnia go (chociaż w systemie Solaris ramki stron są przydzielane z płytami).
Mam nadzieję, że to pomoże. Daj mi znać, jeśli coś wymaga wyjaśnienia.