AmigaOS 4.0 - API i kernel

API AmigaOS 3.1 zawiera około 1100 funkcji. Dla porównania API AmigaOS 4.0 zawiera ponad 1900 funkcji.

Zmiany w API

Największą zmianą w porównaniu z dotychczasowym API znanym z wersji 3.x wprowadzono w sposobie odwoływania się do bibliotek współdzielonych (shared libraries). Dotychczas wywołanie funkcji otwierającej bibliotekę dawało w efekcie adres tej biblioteki, który zobowiązani byliśmy przechowywać w dedykowanej dla tej biblioteki strukturze. W konsekwencji w wersjach 3.x systemu Amigi mieliśmy wiele struktur danych potrzebnych do obsługi funkcji pochodzących z różnych bibliotek. Obecnie OS 4 pozwala używać tylko jeden rodzaj struktur do adresowania wszystkich wskaźników do otwieranych bibliotek.

W zamian za to autorzy najnowszego systemu operacyjnego Amigi wprowadzili warstwę interfejsów rozumianych jako wskaźniki do struktur pozwalających w dynamiczny sposób wywoływać określone funkcje bibliotek. Jest to mechanizm obsadzania adresów funkcji zbliżony do koncepcji metod wirtualnych znanych z języka C++ i zrealizowany za pomocą składni języka 'C'.

Ranger
Program Ranger prezentujący
zależności między procesami
w AmigaOS 4.0.

W przypadku systemu AmigaOS 3.x biblioteka składa się z dwóch zasadniczych części: tablicy skoków i kodu funkcji bibliotecznych. Tablica skoków zawiera listę instrukcji skoku (stąd nazwa) do adresów startowych funkcji umieszczonych w bibliotece, dzięki temu pozwala na przekazywanie tym funkcjom sterowania. Użycie klasycznej tablicy skoków polega na wykonaniu dwóch instrukcji skoku. Pierwszy wykonywany jest do adresu instrukcji w tablicy skoków i skojarzonej z interesującą nas funkcją. Drugi skok wykonywany jest na podstawie odczytanej wartości z tablicy oraz adresu bazowego biblioteki zapamiętanego podczas jej otwierania. Ten skok przenosi sterowanie na początek kodu właściwej funkcji, którą chcemy wykonać.

Struktura opisująca interfejsy w najnowszej wersji systemu operacyjnego Amigi jest podobna do wspomnianej tablicy skoków, lecz zawiera tylko adresy początków kodu poszczególnych funkcji w bibliotece. To pozwala na bezpośrednie przeniesienie sterowania do kodu tych funkcji bez wykonywania dwóch skoków znanych z klasycznej architektury. Każda biblioteka w AmigaOS 4 musi posiadać przynajmniej jeden interfejs zwany głównym (main), poza tym może zawierać interfejsy dodatkowe. Zwiększenie liczby interfejsów bo bibliotek pozwala na ograniczanie dostępu do wybranych funkcji lub zmianę sposobu wykorzystywania zawartości biblioteki w zależności od używanego kontekstu. Takie uelastycznienie dostępu do bibliotek koresponduje z koncepcjami programowania orientowanego obiektowo.

Zarządzanie pamięcią

W AmigaOS 3.x zarządzanie pamięcią sprowadzało się do wykonywania prostych czynności przydzielania żądanych obszarów procesom i zadaniom (tasks) oraz ich zwracania. Te czynności oparte były na mechaniźmie przeglądania i aktualizowania listy wolnych bloków pamięci. Zadanie przydzielenia procesowi obszaru pamięci polegało na odnalezieniu bloku większego od obszaru żądanego i podzieleniu go na dwie części. Jedna o rozmiarze równym żądaniu udostępniana była procesowi, natomiast druga pozostawała na liście wolnych bloków. Po użyciu obszar przydzielony zwracany był do systemu i tworzył nowy wpis na wspomnianej liście. Jak łatwo sobie wyobrazić wraz ze wzrastającą liczbą żądań przydziału pamięci przez wykonywane procesy i kolejnych zwrotów obszarów przydzielonych wzrastał stopień fragmentacji pamięci, czyli jej poszatkowania na coraz większą liczbę coraz mniejszych bloków. Mniejsze bloki oznaczały zmniejszenie szansy przydzielenia odpowiednio dużych bloków następnym chętnym, a wydłużenie listy wolnych bloków spowalniało całą procedurę.

AmigaOS 4.0 przyniósł zasadniczy postęp w tej dziedzinie, wcześniej nie widziany na platformie amigowej. Nowy mechanizm zarządzania pamięcią pozwala nie tylko wyeliminować oba wspomniane wyżej problemy, ale również dokonywać dalszych optymalizacji. Mechanizm ten oparty jest na tzw. alokatorze płytowym (slab allocator) znanym z innych wiodących systemów operacyjnych. Należy przy okazji wspomnieć, że jest to wg. słów braci Frieden ich własna implementacja na podstawie znanej teorii, a nie kod przeniesiony z innych systemów. Skrótowo rzecz ujmując alokator ten zawsze rezerwuje w zasobach pamięci obiekty tego samego rozmiaru. Dostosowuje się do żądań przydziału przez procesy rezerwując większe ilości podstawowych obiektów pogrupowane w tzw. płyty (slabs), które są następnie dzielone na podobszary (bufors) o rozmiarze odpowiadającym żądaniom przydziału. Informacje o przydzielonych podobszarach gromadzone są na listach utrzymywanych przez alokator. Podobnie istnieją odrębne listy obszarów wolnych (nieprzydzielonych). Operacje przydzielania i zwalniania pamięci polegają na modyfikacjach odrębnych list i zachodzą szybciej niż na jednej liście bloków. Takie podejście pozwala również utrzymywać informacje o intensywnie przydzielanych obszarach (często tych samych) w pamięci podręcznej co przyczynia się do dalszego przyspieszenia całej procedury. Należy jednocześnie wspomnieć o tym, że mechanizm alokatora płytowego jest skalowalny i tym samym umożliwia użycie go w architekturze wielordzeniowej lub wieloprocesorowej.

Uruchamianie procesów

Proces RAMLIB jest elementem składowym kernela AmigaOS'u, który pozwala ładować do pamięci sterowniki urządzeń, programy oraz biblioteki współdzielone. W najnowszej wersji systemu operacyjnego Amigi inicjalizacja modułów ładowanych z pamięci masowej odbywa się w odrębnym procesie, co zabezpiecza system przed zawieszeniem w wypadku próby inicjalizowania błędnie napisanego modułu. Takie podejście pozwala jednocześnie przechwycić sterowanie podczas błędnej inicjalizacji, zasygnalizować użytkownikowi problem za pomocą programu Grim Reaper będącego częścią systemu operacyjnego i umożliwić kontynuację pracy lub podjęcie dalszego śledzenia wykonywania błędnego procesu.

Grim Reaper

Grim Reaper jest podsystemem przechwytywania i obsługi wyjątków, czyli sytuacji, w których proces uległ zawieszeniu lub przekroczył w trakcie wykonywania dozwolony obszar pamięci narażając system na destabilizację. Jest to mechanizm o podobnej funkcjonalności do tej jaką świadczył na Amigach klasycznych program Enforcer. Dzięki Grim Reaper'owi użytkownik zyskuje możliwość zapoznania się ze stanem procesu, w którym zaszedł wyjątek (m.in. wartości rejestrów procesora, zawartość stosu, zrzut pamięci zawierającej błędny kod i jego deasemblacja). Użytkownik ma następnie wybór między usunięciem błędnego procesu, kontynuowaniem jego pracy lub kontynuowaniem z jednoczesnym śledzeniem (debugging). Należy przy tym uczciwie powiedzieć, że Grim Reaper nie daje 100% pewności wyjścia z każdego błędu uruchomionych procesów. Radykalnie jednak zmniejsza częstotliwość zawieszeń całego systemu i tym samym poprawia komfort pracy użytkownika.

Grim Reaper
Grim Reaper

autor: Piotr Zadora