Singularity

3 marca 2009

Większość obecnych systemów operacyjnych w mniejszym lub większym stopniu bazuje na dość podobnych założeniach. Nawet jeżeli architektura jądra znacząco się różni (jądra monolityczne, mikrojądra) to i tak wiele pozostałych elementów pozostaje w niewiele zmienionej formie. Istnieją jednak pewne eksperymentalne projekty, mające na celu sprawdzić, jak nowe koncepcje sprawują się w praktyce. Jednym z nich jest rozwijany przez Microsoft Research system operacyjny Singularity.

C# i Sing#

Projekt jest w przeważającej większości napisany w C#. Według danych Microsoftu 95% kodu mikrojądra jest napisana w tym języku. Pozostałe to assembler x86 oraz C++ wykorzystane przy niskopoziomowej obsłudze pewnych podstawowych elementów systemu, o czym później. W tym miejscu nie można nie wspomnieć o Sing#. Jest to zestaw rozszerzeń do C# wspierający wiele dodatkowych mechanizmów często wykorzystywanych w kodzie Singularity. Dodatkowe elementy zawarte w Sing# to między innymi:

  • kontrakty - pozwalają na zachowanie bezpieczeństwa typologicznego podczas komunikacji międzyprocesowej realizowanej przez kanały (channels). Kontrakty definiują jakie wiadomości mogą być przesyłane, typy oraz wymagania co do wartości ich argumentów oraz kierunek w jakim są wysyłane. Kontrakty pozwalają także na ustalenie oczekiwanych komunikatów na każdym etapie transmisji.
  • endpoints - każdy kontrakt definiuje endpointy przeznaczone dla obu stron komunikacji. Zawierają one wszystkie metody opisane w kontrakcie jako możliwe wiadomości i służa do wygodnego ich odbierania i wysyłania.
  • exchange heap - Sing# pozwala na alokację obiektów w specjalnym miejscu przestrzeni adresowej zwanym stertą wymiany (exchange heap), która jest wykorzystywana przez wszelkie rodzaje komunikacji międzyprocesowej. Dodatkowo wykonywane są wszystkie informacje związane z zachowaniem informacji o właścicielu danego obiektu.
  • konstrukcja switch-receive - razem z endpointami pozwala na wygodne odbieranie wiadomości opierając się na standardowej konstrukcji switch.
switch receive {
	case endpoint.Message1() :
		...
		break;
	case endpoint.Message2() :
		...
		break;
}

Bezpieczeństwo

C# (a także wszystkie rozszerzenia związane z Sing#) jest językiem bezpiecznym pod wieloma względami, na czym bazują główne założenia systemu Singularity. Można rozróżnić dwa obszary w których ograniczona została możliwość występowania błędów:

  • bezpieczeństwo typów zapewnia, że wszystkie operacje wykonywane na obiekcie są zgodne z jego typem
  • bezpieczeństwo pamięci zapewnia, że wszystkie odwołania do pamięci są poprawne. Wiąże się to z zerowymi wskaźnikami, odwołaniom poza rozmiar tablicy lub do nieistniejących obiektów.

Bartok

Programy pisane w C# lub innych językach związanych z platformą .NET zwykle są tłumaczone do pośredniego (także bezpiecznego) języka MSIL. Zadaniem kompilatora Bartok, będącego jedną z najważniejszych części Singularity jest tłumaczenie MSIL do kodu natywnego, zachowując przy tym bezpieczeństwo kodu. Odpowiednie optymalizacje pozwalają na stworzenie jak najbardziej wydajnego kodu wykorzystującego wszystkie możliwości danego komputera, co chociaż w pewnym stopniu jest w stanie zrekompensować straty wydajności spowodowane procedurami wsparcia runtime.

Jednolite procesy

Zapewnienie pełnego bezpieczeństwa kodu natywnego wymaga od Singularity wprowadzenie jeszcze dodatkowych ograniczeń w stosunku do procesów (a także i jądra):

  • Kod programu nie może zostać zmodyfikowany w trakcie jego działania.
    Wyklucza to kompilację just-in-time (obecną np. na platformie .NET), a wszystkie dynamicznie konsolidowane biblioteki muszą zostać załadowane przed rozpoczęciem pracy programu.
  • Żaden obiekt nie może należeć do więcej niż jednego procesu w tym samym czasie.
    To ograniczenie ułatwia synchronizację między procesami upraszczając sposób komunikacji między nimi.

Wymaga to między innymi udziału systemu operacyjnego w większości operacji mogących stanowić zagrożenie i tym samym wymusza użycie mechanizmów typu wspomniane wcześniej kontrakty. Istotne jest, że jądro także podlega tym ograniczeniom.

Dzięki tym ograniczeniom możliwe jest także zastosowanie refleksyjności czasu kompilacji (Compile Time Reflection). Żaden element kodu nie może zostać zmieniony w trakcie działania programu, dlatego też refleksyjność realizowana podczas kompilacji (czyli de facto w ostatnim momencie w którym kod może się zmienić) jest w zupełności wystarczająca.

Ochrona pamięci

Najczęstszym obecnie stosowanym mechanizmem mającym za zadanie ochronę przestrzeni adresowej poszczególnych procesów jest stronicowanie. Jako element realizowany sprzętowo HIP wiąże się z pewnymi spadkami wydajności, szczególnie w przypadku komunikacji międzyprocesowej, która wymaga operacjach na katalogu/tablicy stron skutkujących unieważnieniem TLB. Także wywłaszczenie procesu w większości sytuacji unieważnia przynajmniej część wpisów w TLB. Przez bardzo długi czas była to jedna z ważniejszych przyczyn małej popularności mikrojąder.

Każdy program (a także i kernel) w Singularity jest napisany w bezpiecznym języku programowania. Nie może on samodzielnie utworzyć lub unieważnić referencji do obiektów w pamięci a także wykonać żadnych innych operacji, które mogłyby zagrozić bezpieczeństwu systemu. Jedynie alokacja pamięci oraz garbage collector nie spełniają tej zasady, ale są to mechanizmy dostarczane przez system operacyjny i tym samym w pełni zaufane.

Skoro sam język programowania ogranicza programistę do podobnego stopnia jak HIP, sprzętowa ochrona pamięci staje się niepotrzebna. Jej rolę pełnią wszystkie funkcje kontrolne wsparcia runtime, które tym samym tworzą SIP. Wiąże się z tym także założenie, że każdy obiekt może należeć tylko do jednej przestrzeni adresowej. Z tego powodu pamięć współdzielona, a także wszelkie inne sposoby komunikacji międzyprocesowej inne niż kanały (channels) są niedozwolone.

Komunikacja międzyprocesowa

Komunikacja międzyprocesowa w Singularity opiera się na kanałach (channels). Wykorzystują one dodatkowe elementy Sing# opisane wcześniej: kontrakty i endpointy. Dzięki nim utrzymane jest bezpieczeństwo operacji związanych w komunikacją. Cała komunikacja odbywa się przy pomocy endpointów które dostarczają odpowiedni interfejs dla obu uczestników transmisji.

Dane przekazywane są przy użyciu sterty wymiany (exchange heap). W tym miejscu nie funkcjonuje garbage collector, zamiast niego wykorzystywane są liczniki referencji. Jest to obszar pamięci do którego ma dostęp każdy proces, ale zgodnie z zasadami dotyczącymi bezpieczeństwa każdy obiekt przez cały czas ma przyporządkowanego mu właściciela. Przekazanie obiektu odbywa się przez dostarczenie endpointowi odbiorcy wskaźnika na przesyłany obiekt (wewnątrz sterty wymiany).

Sterta wymiany ma też ograniczenia co do obiektów znajdujących się w niej. Przede wszystkim muszą być one wymiennego typu czyli nie mogą zawierać żadnych referencji do innych, nieprzesyłanych obiektów.

Podsumowanie

Singularity jest bez wątpienia bardzo ciekawym, ale też i bardzo rozbudowanym projektem. Ten artykuł opisuje jedynie najbardziej istotne cechy tego systemu, sprawiające, że wyróżnia się on na tle obecnie często stosowanych systemów. Jest to projekt eksperymentalny w którym nie wszystkie rzeczy są jeszcze w pełni ukończone, ale mimo to już zawiera wiele interesujących rozwiązań.

Najprawdopodobniej, w najbliższym czasie pojawi się kolejny artykuł opisujący mniej popularne ale wciąż bardzo istotne elementy systemu Singularity. Być może także pokuszę się o dokładniejsze opisanie któregoś z mechanizmów, bo projekty eksperymentalne zawsze warte są szczególnej uwagi.

Komentarze do wpisu "Singularity" zablokowane.

1. hells.of.iron napisał(a):
3 marca 2009, 22:43:10

"Być może także pokuszę się o dokładniejsze opisanie któregoś z mechanizmów"

Ja pokuszę się o subskrypcję :)

Fajnie, że ktoś tu porusza ciekawe zagadnienia związane z OS'ami. (Coś na zupełnie innym poziomie niż "wyszło nowe łubudubu 50.20", "kde jest super"...)

2. BTM napisał(a):
3 marca 2009, 23:16:00

"Żaden obiekt nie może należeć do więcej niż jednego procesu w tym samym czasie."

Czy chodzi o to, że żadne dwa programy nie mogą np. jednocześnie operować na tych samych komórkach pamięci? Jeżeli tak, to szlag trafia nieco ideę cache. Ale pewnie się mylę, bo nie jedna mądra głowa by już na to wpadła :)

3. Paweł Dziepak napisał(a):
3 marca 2009, 23:25:50

W przypadku tego ograniczenia chodzi o pamięć współdzieloną, która za wyjątkiem "strzeżonej" przez system sterty wymiany nie ma prawa istnieć. Więc, tak, dwa programy nie mogą jednocześnie mieć dostępu do tych samych komórek pamięci, ponieważ wymagałoby to dodatkowego wsparcia dla synchronizacji. W Singularity jej rolę pełni przynależność obiektu do procesu. Przekazując "prawo własności" danego obszaru pamięci (i tak musi być na stercie wymiany) innemu procesowi (a konkretnie odpowiedniemu endpointowi) zezwala mu się na dostęp do tego obiektu, ale poprzedni właściciel w tym momencie go traci.

4. sprae napisał(a):
4 marca 2009, 02:43:17

Wpis bardzo dobry, lecz obawiam się, że konstrukcja swich-recive wydaje się wygodna. Mnie to przypomina bebechy WinLoop. Jako programista wolałbym w systemie obiektowym opartym na jakiejś formie c# - delegaty, eventy, jakąś czystą formę kontrolera?

5. stronger napisał(a):
4 marca 2009, 12:07:20

Świetny tekst, Paweł. Może znasz, a może nie - podcast z kierownikiem projektu Singularity na Software Engineering Radio:

http://www.se-radio.net/podcast/2008-03/episode-88-singularity-research-os-galen-hunt

6. Ktos napisał(a):
4 marca 2009, 18:35:10

A propos Singularity: http://singularity.codeplex.com/ jeśli ktoś chce sobie zobaczyć, przejrzeć, zbudować i tak dalej :-)

7. Paweł Dziepak napisał(a):
4 marca 2009, 23:29:29

@sprae: switch receive może i nie jest typowo obiektowym rozwiązaniem, ale w tym zastosowaniu wydaje się w miarę uzasadnione. Przede wszystkim jedna taka konstrukcja pozwala na obsługę wielu endpointów jednocześnie. Przykładowy kod może zostać wykonany jedynie wtedy gdy otrzymane zostaną wiadomości na paru endpointach jednocześnie. Coś takiego już nie uda się w równie prosty sposób zrealizować przy pomocy delegatów.

8. pp napisał(a):
15 października 2009, 17:11:36

Witam może z innej beczki znalazłem OS finasowany przez M$ barrelfish.org narazie początek na BSD licencji.
co myślicie o tym OS