Linux a czas rzeczywisty
Wprowadzenie do systemów RT:

RTLinux:

KURT Linux:

Slajdy:

Architektura RTLinuksa

(wszystkie podane czasy wykonania dotyczą procesora klasy Pentium III 800 MHz)

Wielozadaniowy system operacyjny może szeregować procesy na jeden z dwóch sposobów:

  • kiedy wydarzy się coś ważnego, np. nadejdzie przerwanie, wzrasta priorytet procesu, który na nie czeka, i zostaje on uruchomiony. Będzie działał przez jakiś ustalony przedział czasu (timeslice), albo do czasu następnego ważnego wydarzenia. Tak działa system wielozadaniowy z wywłaszczeniem (preemptively multitasked OS).
  • proces musi sama zgłosić swoją gotowość do zmiany kontekstu - np. poprzez wywołanie funkcji schedulera. Nazywa się to wielozadaniowością kooperatywną (cooperative multitasking).

W Linuksie, procesy mogą pracować w jednym z dwóch trybów: w przestrzeni użytkownika, wykonując własny kod, albo w przestrzeni jądra, wykonując funkcję systemową lub jakąś inną część kernela. Proces pracujący w przestrzeni jądra działa do czasu, aż postanowi się zatrzymać, ignorując timeslice'y i ważne wydarzenia. Jeśli ważniejszy proces staje się gotów do uruchomienia, nie może zostać uruchomiony, dopóki aktualny proces nie wydostanie się z trybu jądra. W pesymistycznym przypadku może to trwać nawet kilkaset milisekund (najczęściej czas ten jednak nie przekracza 16 ms).

Istnieją patche na jądro pozwalające zmniejszyć ten czas do około 1 milisekundy, poprzez zwiększenie ilości miejsc, w których może nastąpić wydziedziczenie, w samym jądrze. W niektórych zastosowaniach nawet 1 milisekunda to zbyt długo. Poza tym, patche takie mają inne wady: komplikują kod kernela (każdy, kto go widział, wie, że to ostatnia rzecz, której ów potrzebuje), a poprawność programów pracujących w czasie rzeczywistym nadal jest bardzo trudna do udowodnienia.

Rozwiązanie użyte w RTLinuksie jest zupełnie inne. Tak naprawdę, mamy tu doczynienia z dwoma systemami operacyjnymi: podstawowym jest RTCore, mały, wywłaszczający system czasu rzeczywistego. Zawiera same podstawowe funkcje - bez zaawansowanych, o niewiadomym czasie wykonania, takich jak na przykład cachowanie danych odczytanych z dysku czy dynamiczna alokacja pamięci. Pod jego kontrolą pracują procesy czasu rzeczywistego. Jednym z nich - o najmniejszym priorytecie, tak, jak idle w Linuksie - jest pełen, duży system operacyjny ze wszystkimi funkcjami, nie pracujący w czasie rzeczywistym: w chwili obecnej może to być Linux lub BSD. Pod kontrolą dużego systemu operacyjnego pracują procesy nie wymagajace czasu rzeczywistego. Kiedy procesy czasu rzeczywistego nie mają nic do roboty, sterowanie zostaje przekazane do dużego SO, który zarządza własnymi procesami - aż do czasu, kiedy któryś z procesów działających w czasie rzeczywistym musi zostać uruchomiony, duży SO zostaje wtedy wywłaszczony przez RTCore i włączony zostaje oczekujący na uruchomienie proces czasu rzeczywistego.

Rozwiązanie to:

  • zapewnia terminowe wykonanie procesów czasu rzeczywistego (pesymistyczny czas oczekiwania procesu czasu rzeczywistego nie przekracza około 12 mikrosekund! To mniej więcej 100 razy szybciej, niż kernel z patchami zmieniającymi jądro na wywłaszczające, i ponad 1000 razy szybciej, niż 'gołe' jądro!)
  • pozwala procesom nie wykonującym się w czasie rzeczywistym na korzystanie z udogodnień dawanych przez 'duży' system operacyjny
  • w minimalnym stopniu zmienia kod kernela dużego systemu
  • pozwala - wymusza wręcz - podział aplikacji na fragmenty wymagające czasu rzeczywistego i na czasu rzeczywistego nie wymagające. Na przykład, aplikacja pobierająca dane z czujnika dokładnie co milisekundę i wyświetlająca te dane na ekranie w postaci jakiegoś wykresu może dzielić się na moduł pobierający dane, działający w czasie rzeczywistym, i przekazujący te dane do modułu rysującego wykres w X-ach, korzystającego z zaawansowanych fukcji systemu operacyjnego i nie wymagającego czasu rzeczywistego. Ułatwia to testowanie i weryfikację aplikacji.

Przyjęte rozwiązanie oznacza, że procesy RT pracują w przestrzeni jądra. Ich ładowanie i wyładowywanie odbywa się dzięki systemowi modułów - każdy program RT to oddzielny moduł. Oznacza to w szczególności, że wadliwy program RT może zawiesić cały system operacyjny. Dość długo nie było to przez twórców uznawane za problem - jak mówi Yodaiken, "o ile aplikacji z powodu niewłaściwego wskaźnika nie uda się zatrzymać w porę 20-tonowej prasy hydraulicznej, to niewielka pociecha z tego, że system operacyjny będzie działał dalej" - ostatnio jednak dostrzeżona została potrzeba wątków RT wykonujących się w przestrzeni użytkownika i dano programom możliwość tworzenia ich.

UWAGA: jako, że procesy RT mają wspólną przestrzeń adresową, słowa 'proces' i 'wątek' są w znajdujących się na tej stronie materiałach dotyczących RTLinuksa używane wymiennie.

Jak mówi w jednym z wywiadów sam Yodaiken, "Kluczowymi dla RTLinuksa zasadami są: a) Linux nie może spowalniać komponentu RT, i b) komponent RT musi być prosty."

RTLinux podzielony jest na moduły, podstawowy - zawierający kontroler przerwań i niewiele więcej - i opcjonalne: scheduler, kolejki FIFO działające w czasie rzeczywistym, POSIXowe operacje wejścia / wyjścia, timery i obsługę pamięci dzielonej. Rozwiązanie to umożliwia załadowanie jedynie tych modułów, które są naprawdę potrzebne - i, dzięki temu, zmninimalzowanie rozmiarów komponentu RT - oraz łatwą modyfikację RTLinuksa: o ile np chcemy zastąpić dostarczony scheduler własnym, wystarczy załadować inny moduł.