Wirtualizacja "właściwa" - szczegóły techniczne

Wstecz
Dalej
Indeks

Jak działa wirtualizacja

Poniższy rysunek przedstawia typowy sposób wirtualizacji sprzętu.


Schemat wirtualizacji sprzętu

Program wirtualizujący składa się zazwyczaj z dwóch części - aplikacji uruchomionej w systemie-gospodarzu w trybie użytkownika, i z monitora maszyny wirtualnej (ang. Virtual Machine Monitor) uruchomionego w trybie systemu operacyjnego, zazwyczaj jako dodatkowy moduł lub serwis/demon. System-gość jest uruchomiony spod aplikacji wirtualizatora, także w trybie użytkownika.

Kod systemu-gościa (i jego aplikacji) jest wykonywany bezpośrednio na procesorze gospodarza, jednakże jest on po drodze monitorowany przez proces VMM. Monitor zajmuje się wynajdowaniem niebezpiecznych instrukcji w kodzie gościa (jest do tego potrzebny poziom uprzywilejowania systemu). Gdy ten chce wykonać jedną z nich, VMM wykrywa to i informuje o tym aplikację wirtualizatora. Wirtualizator z kolei emuluje działanie tej instrukcji w przestrzeni użytkownika. Dzięki temu system-gość "nie zauważa różnicy".

Czasem system-gość może zażądać dostępu do urządzenia zewnętrznego. VMM wychwytuje te żądania, a następnie aplikacja wirtualizatora emuluje wybrane urządzenie zewnętrzne.

Problemy związane z wirtualizacją i ich rozwiązania

Programu systemu-gościa nie można wykonać na procesorze gospodarza w całości, bez wyjątku. System-gość wymaga zazwyczaj wysokiego poziomu uprzywilejowania, zatem jego uruchomienie na tymże poziomie konfliktowałoby z pracą gospodarza, poza tym system-gość zauważyłby, że nie pracuje natywnie. Trzeba zatem wykrywać instrukcje niebezpieczne, przerwania itp. i emulować ich działanie, aby system-gość uważał dostępne dla siebie środowisko jako "prawdziwe".

Pierwszym krokiem jest uruchomienie kodu systemu-gościa na poziomie uprzywilejowania użytkownika - dzięki temu niebezpieczne instrukcje gościa nie wykonają się, ale wywołają błąd ochrony, który może być przechwycony przez VMM.

Niestety, w popularnej architekturze Intel x86 to nie wystarcza - część instrukcji niebezpiecznych może wykonywać się na poziomie użytkownika nie wywołując żadnych sygnałów dla VMM. Zachodzi potrzeba wykrycia tych instrukcji samodzielnie, stosuje się w tym celu przeróżne techniki. Oto przykład:

Załóżmy, że wykonujemy kod, który na pewnej pozycji ma jedną z takich niebezpiecznych instrukcji. Aby ją odnaleźć, VMM może dynamicznie przeglądać kod (przeglądanie kodu jest szybsze niż jego interpretacja i wykonywanie, więc narzut wydajnościowy jest mały w porównaniu z emulacją). Po znalezieniu groźnej instrukcji, VMM musi uniemożliwić gościowi jej wykonanie. Na przykład może podmienić instrukcję na polecenie skoku do własnej podprocedury, i tam zająć się jej emulacją. Problem zachodzi, gdy gość wykonuje samomodyfikujący się kod - wtedy zmiana wykonana przez VMM może nie być skuteczna, nie mówiąc o tym, że gość mógł wstawić niebezpieczną instrukcję do kawałka kodu już przeskanowanego przez VMM. Temu z kolei można zapobiec, umieszczając kod gościa w segmencie pamięci tylko-do-odczytu - wtedy próba zmiany kodu przez gościa spowoduje wyjątek możliwy do przechwycenia przez VMM. Jednakże nie rozwiązuje to innego kłopotu, gdy gość chce odczytać wartość ze podmienionej przez VMM komórki pamięci - powinien tam odnaleźć kod, jaki był wpisany przed zamianą. Zatem VMM musi wyszukiwać w kodzie także instrukcje odczytu z pamięci...

Inne problemy związane z wirtualizacją zawierają: konieczność tłumaczenia wirtualnych adresów pamięci na rzeczywiste, wirtualizacji zegarów systemowych i wiele innych. Bardzo szczegółowe omówienie wielu problemów znajdziemy w pracy Kevina Lawtona nt. wirtualizacji.

Wróć do góry