Michał Matuszewski
W systemie Windows NT każdy z procesów widzi przestrzeń adresową 4 GB pamięci. Z tego dolne 2 GB mogą być wykorzystywane przez proces użytkownika, a górne 2 GB są zarezerwowane dla jądra systemu (są takie same dla każdego procesu). W obszarze dolnym również mogą się znajdować obszary zarezerwowane przez system, np. biblioteki DLL załadowane przez dany proces.
Począwszy od NT 4.0 Enterprise Edition zostało wprowadzone rozszerzenie pamięci użytkownika do 3 GB, ze względu na wymagania aplikacji. W takim modelu jądro ma do dyspozycji jedynie 1 GB górnej przestrzeni adresowej.
Podobnie jak w Linuksie, w przestrzeni 4 GB pamięci mogą się znajdować obszary odpowiadające fizycznej pamięci, pamięci w postaci plików wymiany, mogą być również obszary wolne. Możliwe jest też odwzorowanie adresów wirtualnych do innych plików, np. plików z kodem programu czy plików z danymi. Każdy obszar pamięci fizycznej lub dyskowej może być przyporządkowany różnym procesom pod dowolnymi adresami wirtualnymi.
Konkretny sposób adresowania pozostawia się najczęsciej procesorowi (tak jest dla i386 i Alphy) w przypadku stron poprawnych i zależy tylko od systemu dla stron niepoprawnych. Ponieważ obecne procesory udostępniają zazwyczaj kilka mechanizmów adresowania, wybór konkretnej implementacji spośród dostępnych należy do systemu. Windows NT nie stosuje żadnej segmentacji, w szczególności rejestry segmentowe procesora rodziny i386 są zawsze ustawione tak, aby wskazywały na początkowe 4 GB pamięci fizycznej.
Pamięć wirtualna jest podzielona na ramki o wielkości zależnej od platformy sprzętowej. Na i386 jest to 4 KB, dla procesorów DEC Alpha jest to 8 KB. Podobnie jak to ma miejsce w systemie Linux, adres wirtualny w WinNT jest podzielony, ale składa się z trzech części. Adres katalogu stron jest przechowywany w rejestrze procesora (inny dla każdego procesu). Pierwsze bity adresu wirtualnego to pozycja w katalogu stron pola PTE (Page Table Entry). Ten z kolei wskazuje na adres tabeli stron. Kolejne bity adresu wirtualnego to pozycja w tejże tabeli, zawierającej PTE wskazujące na konkretną ramkę. Ostatnie bity adresu to offset w ramce.
W podstawowym modelu maksymalna wielkość pamięci fizycznej to 4 GB. Są jednak rozszerzenia w sytemach Windows 2000 i późniejszych, które pozwalają pokonać to ograniczenie. Na procesorach Alpha naturalne jest adresowanie 32 GB pamięci, ze względu na rozmiar ramki wynoszący 8 KB. Na platformach i386 technika Physical Address Extension (PAE) wykorzystuje mechanizmy obecne w procesorach Pentium Pro i późniejszych do zaadresowania 64 GB pamięci. Rozszerzenie adresu wirtualnego z 32 do 36 bitów realizowane jest przy pomocy Address Windowing Extension (AWE API).
Pole PTE zawiera adres fizyczny ramki. Na procesorze i386 spośród 32 bitów użyte jest na to tylko 20, pozostałe bity są wykorzystane do informacji o stanie strony. Pięć z 12 bitów używa się do oznaczenia zabezpieczenia strony przed niepowołanym dostępem, cztery do oznaczenia pliku wymiany, w którym znajduje się strona (a więc jest maksymalnie 16 plików wymiany), a trzy do oznaczenia jej stanu (czy strona jest w pamięci czy na dysku i jaki jest jej aktualny status). Ten standardowy podział może się jednak zmieniać, w zależności od typu strony. Przykłady znaczenia poszczególnych bitów:
Jeżeli strona znajduje się w pliku wymiany, 20-bitowy adres wskazuje na jej pozycję w pliku. Jeżeli strona jest zamapowanym plikiem, np. fragmentem pliku wykonywalnego, lub dużego pliku z danymi, 28 bitów jest indeksem w tablicy systemowej zawierającej nazwę i ścieżkę pliku oraz pozycję.
W przypadku, gdy strona, do ktorej następuje odwołanie, nie znajduje się w pamięci fizycznej, następuje błąd braku strony. W skrajnym przypadku może to spowodować odczyt trzech stron z dysku (strony zawierającej katalog, tablicę stron i samej strony). Aby uniknąć takich przypadków, stosuje się algorytm pola roboczego (working set) i rejestry podręczne TLB (Table Lookaside Buffers). Będą one opisane w dalszej częsci.
Jeżeli występuje konieczność wczytania strony do pamięci, automatycznie jest wczytywane także kilka sąsiadujących stron, bo jest duże prawdopodobieństwo, że one również będą potrzebne.
Istnieją obszary pamięci, które nie podlegają stronicowaniu, zwane nonpaged pools. Nie mogą one być zrzucone do pliku wymiany. W takim obszarze znajduje się kod menedżera pamięci wirtualnej. Nie można umieścić w takim obszarze żadnej z częsci programu użytkownika. Jest jednak możliwe tzw. przypinanie stron, które pozwala na umieszczenie danej strony na stałe w pamięci komputera (służy do tego funkcja VirtualLock). Nie zaleca się przypinania stron, ponieważ zazwyczaj powoduje to więcej szkody niż pożytku (zajmuje ona miejsce w polu roboczym, o czym czytaj niżej).
Każdy proces ma początkowo przydzieloną pewną ilość stron, które będą na pewno przebywać w pamięci fizycznej. Jest to pole robocze procesu. Dokładniej jest zadana minimalna i maksymalna wielkość pola roboczego. Jeżeli aktualnie jego wielkość nie jest równa minimalnej, podlega ono przycinaniu (trimming). Proces zarządzający pamięcią wirtualną w celu optymalizacji okresowo zmniejsza ilość stron w polu roboczym procesu. Jeżeli nie generuje to zbyt dużej ilości błędów braku strony, pole robocze jest zmniejszane na stałe, a nadmiarowe strony trafiają do zbioru stron ogólnego użytku dla wszystkich procesów.
Zmniejszanie pola roboczego przebiega w dwóch fazach. Na początku strona nie jest usuwana z pamięci, a jedynie oznaczana jako niepoprawna w polu PTE. Odwołanie do takiej strony generuje jedynie programowy błąd braku strony, a nie stwarza konieczności odczytania jej z dysku. Następnie strona jest oznaczana jako Modified lub Standby zależnie od tego, czy została zmodyfikowana czy nie, przez co może być zrzucona na dysk przez menedżera pamięci.
Proces może sam określać rozmiar pola roboczego, jeśli ma do tego uprawnienia (służy do tego funkcja SetProcessWorkingSetSize). W pewnych przypadkach możliwe jest całkowite wywłaszczenie procesu ze stron w pamięci, jeżeli jest on przez długi czas nieaktywny, na przykład jeśli jest aktywny tylko przy logowaniu. Jeżeli proces wróci do aktywności, musi być odczytane z pliku wymiany całe jego pole robocze.
W systemie Windows NT rozróżnia się obszary pamięci zarezerwowanej (reserved) i zatwierdzonej (commited). Wątek, który chce uzyskać oszar pamięci, musi na początku zarezerwować pewną strefę adresową. Może być ona duża, nawet większa od dostępnej pamięi fizycznej, ponieważ nie następuje jeszcze przydzielenie pamięci. Następnie wątek zatwierdza wybrane części lub całą strefę pamięci, którą zarezerwował. W tym momencie system przyporządkowuje adresom pamięć fizyczną lub część pliku wymiany. Dzięki temu mechanizmowi wątek ma pewność, że żaden inny wątek w tym samym procesie nie będzie korzystał z zarezerwowanej przestrzeni adresowej.
Ponieważ adres komórki pamięci może być dowolny dla każdego z procesów, konieczne jest zastosowanie pewnej techniki pamięci dzielonej. Służą do tego prototypowe PTE. Pola PTE poszczególnych procesów, opowiadające stronie pamięci dzielonej wskazują nie na ramkę pamięci danych, ale na prototypowy PTE, który z kolei wskazuje na docelowy blok pamięci dzielonej. W całym systemie 8 MB przestrzeni adresowej przeznaczone jest na prototypowe PTE. Są one tworzone dopiero wtedy, gdy są potrzebne, więc nie jest tracona na nie pamięć fizyczna.
Niektóre obszary pamięci dzielonej, np. kod programu mogą być tylko w nietypowych przypadkach zmieniane w jednym z procesów współdzielących pamięć. Weźmy pod uwagę dwa procesy równolegle wykonujące ten sam kod. Nie ma powodu, aby przydzielać im dwa oddzielne obszary pamięci fizycznej na kod programu, więc tworzy się obszar pamięci dzielonej. Kiedy jednak stawiamy pułapkę w debuggerze dla jednego z tych procesów, zachodzi potrzeba skopiowania fragmentu kodu dla jednego z procesów. Stosuje się tutaj optymalizację copy-on-write.
System Windows NT prowadzi bazę danych stron. Jest ona używana przez proces zarządzający pamięcią wirtualną do przydzielania i zwalniania stron pamięci. Wszystkie strony dzielą się na siedem kategorii. Strony jednej kategorii są połączone w listę.
Kod wykonywalny procesu zarządzającego znajduje się w pliku NTOSKRNL.EXE. Dzieli się on na sześć wątków o różnym priorytecie. Najważniejszy z nich to Balance Set Manager. Zajmuje się on dobieraniem wielkości pól roboczych, uruchamia inne wątki w razie potrzeby, np. wątku zerującego zwolnione strony w celu ponownego użycia. Wybiera strony, które mają być wyrzucone z pamięci, przybliżając algorytm LRU za pomocą bitów dostępu do strony.
Aby właściwie zarządzać pamięcią, oprócz tablic wskaźników PTE i bazy danych stron konieczne jest posiadanie pewnej informacji o tym, co dane ramki faktycznie reprezentują. Za każdym razem, kiedy tworzony jest obszar pamięci dla procesu i przydzielane są ramki pamięci wirtualnej, konstruuje się strukturę opisującą, co znajduje się w tych ramkach, na przykład kod programu, biblioteki DLL czy blok danych używany przez konkretny proces. Struktura ta nazywa się Virtual Address Descriptor (VAD). Każdy proces może mieć wiele takich struktur. Są one połączone w rodzaj drzewa binarnego (drzewo typu splay), dzięki czemu łatwy jest dostęp do ostatnio używanych VAD-ów, i szybkie jest wyszukiwanie.
System udostępnia uprawnionemu procesowi funkcję VirtualQuery, która podaje strukturę danych opisującą kolejne bloki pamięci wirtualnej. Zawiera ona adres, rozmiar i prawa dostępu do bloku pamięci, stan (zarezerwowany, zatwierdzony, wolny). Jeżeli blok jest zatwierdzony lub zarezerwowany, to zawiera ona informacje o tym, jaki był adres i prawa dostępu do bloku pamięci w momencie rezerwowania (zobacz punkt 6). Jeden blok zarezerwowany może się rozpaść na wiele bloków zarezerwowanych, zatwierdzonych, i wolnych na skutek zatwierdzania i zwalniania pamięci wewnątrz bloku.
This document was generated using the LaTeX2HTML translator Version 2002 (1.62)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html -html_version 3.2,latin2,unicode -split 0 -nosubdir -nonavigation ntvm.tex
The translation was initiated by Michal Matuszewski on 2002-12-03