Do strony głównej modułu Pamięć
Błędy braku i ochrony strony są to specjalne sytuacje wyjątkowe, zgłaszane przez procesor w przypadku gdy program użytkownika próbuje się odwołać do obszaru pamięci, do którego z rozmaitych powodów nie ma praw dostępu. U źródeł powstania takich mechanizmów leżała chęć zabezpieczenia systemów operacyjnych przed wpływem źle napisanych programów a także umożliwienie korzystania z zaawansowanych metod zarządzania pamięcią wirtualną (np. stronicowanie na żądanie - ang. paging on-demand)
W dokumencie tym postaramy się skupić na środkach sprzętowych dostępnych w procesorze Intel i386 i nowszych, jako że ich znajomość jest konieczna do zrozumienia niektórych metod zarządzania pamięcią. Pokażemy również, jak możliwości sprzętu zostały wykorzystane przez twórców systemu do implementacji poszczególnych strategii gospodarowania tym zasobem.
Realizacja mechanizmu ochrony pamięci wymaga wsparcia sprzętowego. Procesor musi mieć możliwość definiowania praw odczytu/zapisu poszczególnych jej regionów a także zgłaszania naruszenia tych praw za pomocą mechanizmu przerwań.
Procesory Intela posiadają mechanizm wyjątków ("exceptions"), czyli przerwań generowanych przez procesor podczas wykonywania programu. Istnieje możliwość zdefiniowania własnych procedur ich obsługi, co sprawia, że mechanizm ten staje się użytecznym narzędziem przy implementacji systemu zarządzającego pamięcią. .
Z punktu widzenia zarządzania pamięcią interesują nas jedynie dwa zgłaszane przez procesor wyjątki. Pierwszy z nich powstaje w przypadku wykrycia błędu już na etapie segmentacji, drugi generowany jest w przypadku błędu translacji adresu logicznego na fizyczny na poziomie mechanizmu stronicowania. Więcej informacji na temat powstawania wyjątków znajduje się w dalszej części dokumentu.
Procesor wywołując odpowiednią procedurę obsługi wyjątku związanego z odwołaniem do pamięci przekazuje jej następujące informacje:
Podczas startu systemu Linux funkcja inicjalizacyjna instaluje procedurę obsługi wyjątku. Została ona napisana w assemblerze i386 i służy tylko do zachowania stanu procesora, zawartości rejestrów a następnie przekazania tych informacji do procedury " do_page_fault" zapisanej w języku C, która zajmuje się dalszą obsługą błędu.
asmlinkage void do_page_fault(struct pt_regs *regs,
unsigned long error_code)
Parametr regs wskazuje na kopię zawartości rejestrów procesora w momencie wystąpienia błędu, potrzebną do wznowienia działania procesu po obsłużeniu sytuacji wyjątkowej, a error_code niesie informacje o przyczynie jego wystąpienia.
Aby obsłużyć błąd strony procedura do_page_fault wyznacza adres liniowy miejsca jego wystąpienia, a następnie na jego podstawie obszar pamięci, którego błąd dotyczy.
W przypadku gdy poprawne zidentyfikowanie obszaru gdzie wystąpił wyjątek okaże się niemożliwe, aktualnie wykonywany proces zostaje przerwany, gdyż prawdopodobnie doszło do zniszczenia jego struktur danych i istniałoby niebezpieczeństwo załamania systemu.
W przypadku gdy obszar pamięci okazał się poprawny, następuje wywołanie odpowiedniej procedury obsługi zaistniałej sytuacji.
Powrót do spisu treści
System obsługi błędów strony nie posiada żadnych poważniejszych struktur danych. Gromadzona jest jedynie statystyka ilości wystąpień wyjątków dla każdego zadania.
Najlepszym sposobem na przybliżenie sposobu działania mechanizmu wyjątków i pokazania jego znaczenia dla zarządzania pamięcią jest podanie kilku przykładów.
Pierwszy z nich powstaje na etapie translacji adresu na poziomie segmentów. Obejmuje on następujące przypadki:
Drugi z wyjątków ("page fault") zostaje zgłoszony w przypadku błędu translacji adresu na poziomie mechanizmu stronicowania. Obejmuje to następujące przypadki:
Ogólnie system Linux zakłada 3-poziomowy mechanizm translacji adresu logicznego na fizyczny. W przypadku procesora i386 mamy dostępne sprzętowo tylko 2 poziomy struktur danych: katalog tablic stron i tablice stron.
Katalog tablic stron to specjalna strona (o rozmiarze 4KB) w pamięci związana z procesem, która zawiera 1024 adresy poszczególnych tablic stron. Odpowiednią tablicę wybieramy na podstawie 10 najbardziej znaczących bitów adresu logicznego. Po odczytaniu z katalogu adresu tablicy stron odczytujemy z niej adres właściwej strony pamięci, do której chcemy się odwołać. Każda tablica stron zawiera informacje o maks. 1024 stronach w pamięci, więc teoretycznie może służyć do zarządzania 4 MB danych.
Poszczególne pozycje tablicy stron oprócz adresów ramek zawierają także pewne bity dodatkowe, takie jak informacja czy strona znajduje się w pamięci czy była ostatnio odczytywana i/lub zapisywana, jakie są uprawnienia do czytania/pisania itp.
Operacja translacji adresu logicznego na fizyczny jest dokonywana przed wykonaniem każdej instrukcji maszynowej przez procesor. W przypadku gdy na podstawie informacji odczytanej z tablicy stron okaże się, że żądanej strony nie ma w pamięci, procesor generuje przerwanie błędu braku strony (page fault). Jeśli strona jest, natomiast odpowiednie bity w tablicy stron kolidują z trybem dostępu do niej (np. jeśli strona jest tylko do odczytu a program użytkowy próbuje pisać) to także zgłaszane jest przerwanie błędu strony.
Poprzez odpowiednią konstrukcję katalogów oraz tablic stron dla każdego procesu można uzyskać dwie rzeczy - ochronę przestrzeni adresowej procesów oraz pamięć wirtualną. W celu uzyskania ochrony wystarczy tak skonstruować odpowiednie tablice, by odwołanie do niepożądanego adresu spowodowało zgłoszenie przez procesor wyjątku. W przypadku pamięci wirtualnej wyzerowanie bitu "present" na odpowiedniej pozycji w tablicy stron również spowoduje zgłoszenie wyjątku. Wystarczy więc tak skonstruować procedurę jego obsługi, by na podstawie informacji dostarczonych przez procesor rozpoznała typ wyjątku i podjęła stosowną akcję, kończąc niebezpieczny proces lub sprowadzając nieobecną stronę z urządzenia wymiany. Aby cały ten mechanizm okazał się skuteczny, musi być przezroczysty dla działających w systemie procesów.
Aby to zapewnić niezbędna jest możliwość wznowienia instrukcji powodującej zgłoszenie wyjątku. Tak też jest w przypadku procesorów Intela. Wykonanie instrukcji podzielone jest na kilka etapów. Jednym z nich jest translacja adresów fizycznych na logiczne. Wtedy też następuje ewentualne zgłoszenie wyjątku, bez wykonywania instrukcji. Tak więc po usunięciu warunków uniemożliwiających wykonanie instrukcja może być powtórzona, bez obaw o skutki uboczne.