systemy_czasu_rzeczywistego:synchronizacja

Zasadniczą techniką synchronizacji procesów jest użycie w tym celu semaforów.

    S = > 0 − zezwolenie na kontynuację
      = 0 − brak zgody na kontynuację

Semafor (semaphore) S jest zmienną systemową, której wartość może być sprawdzana i zmieniana przez wszystkie zadania za pomocą jednej z dwóch instrukcji:

     Wait(S)  if S >0 then
                    S = S – 1
              else
                    zawieś wykonywanie zadania

     Post (S) if istnieje zadanie zawieszone then
                   wznów jedno zdanie
              else
                   S = S + 1

Obie te operacje są niepodzielne, co oznacza, że w danej chwili może być wykonana tylko i wyłącznie jedna z nich. Raz rozpoczęte muszą się zakończyć. W tym czasie żaden inny proces nie może ich wywołać. Są implementowane w jądrze systemu co daje szereg zalet jak np. dostępność dla wszystkich procedur działających w systemie, operacja czekaj może zablokować wykonywanie jakiegoś procesu, co powinno spowodować przejście do innego a sygnalizuj może uczynić proces wykonywalnym.

Jądro może udostępniać wiele rodzajów semaforów:

1. Semafor binarny - semafor, który może przyjmować tylko jedną z dwu możliwych wartości: 1 lub 0. Operacja opuszczenia polega na zmniejszeniu jego wartości o jeden jeśli jest to możliwe. Tak, więc jeśli semafor ma wartość 1, to wówczas przyjmuje wartość 0. Jeśli natomiast jest już “wyzerowany”, to uważany jest jako “niedostępny” lub “pusty” a zadanie wykonujące taką operację jest blokowane. Operacja podniesienia takiego semafora kieruje się zasadą, że jeśli istnieją procesy wstrzymane w wyniku jego opuszczenia, to jeden z nich jest wznawiany. W przeciwnym wypadku semafor przyjmuje wartość 1.

2. Semafor ogólny - semafor, który posiada więcej niż dwa stany. Może być zajmowany oraz zwalniany wiele razy. Mówiąc bardziej obrazowo, jego wartość określa liczbę dostępnych w systemie jego kopii. Każde zadanie może pobrać jakąś ich ilość i jeśli zacznie ich brakować, to wówczas zadania zgłaszające ich żądanie będą blokowane.

3. Muteksy - stanowią szczególny rodzaj semaforów binarnych. Ich stany określa się inaczej niż to było pokazane wcześniej dla semaforów binarnego i ogólnego. Muteks może być zablokowany (ma wartość 1) lub odblokowany (ma wartość 0 - nie zablokowany. Nowa cechą dla muteksów jest zasada posiadania. Otóż polega ona na tym, że jeśli jakieśzadanie zablokuje muteks (nada mu wartość 1), to tylko ono może ten muteks odblokować(nadać mu wartość 0). Eliminuje to całkowicie najważniejszy problem semaforów, jakim jest fakt, że są one globalne i dowolny proces może je opuszczać albo podnosić. Kolejnym udogodnieniem, jakie się często spotyka jest możliwość blokowania muteksów w sposób rekurencyjny. Określa to wyłączenie ile razy zadanie, które posiada dany muteks wykonało na nim operację blokowania.

Kolejnym mechanizmem synchronizacji procesów są zmienne warunkowe. Pozwalają one wielokrotnie wstrzymywać wykonanie jakiegoś zadania, aż żądany warunek zostanie spełniony. Kiedy zadanie sprawdza daną zmienną warunkową, musi mieć dostęp do niej na wyłączność. Dlatego też, dostęp do nich musi być chroniony przez muteksy, uniemożliwiające zmianę ich stanu podczas odczytu,

Jak widać, w pierwszym kroku zadanie nr 1 blokuje chroniący zmienną warunkową muteks oraz sprawdza ją. Niestety, stan zasobu powiązanego z tą zmienną nie spełnia wymagań i w kroku drugim oraz trzecim zadanie “wędruje” do listy zadań oczekujących, zwalniając jednocześnie muteks. W kolejnym kroku, zadanie nr 2 blokuje dostępny muteks, wykonuje jakieś operacje na zasobie współdzielonym oraz zwalnia go, zapisując ten fakt w zmiennej warunkowej. Następnie, w kroku piątym, wykonuje operację informującą zadania oczekujące, że warunek został zmieniony. Wówczas wybrane zadanie z kolejki (w tym przypadku zadanie nr 1), ponownie blokuje muteks, sprawdza warunek (ponowne sprawdzanie warunku powoduje uniknąć sytuacji, w której operacja sygnalizowania jest błędnie wykonana i najczęściej jest implementowane w postaci pętli while) oraz zajmuje zasób.

Skrzynki także służą do synchronizacji zadań. Tworzą one bufor danych mogących przechować określoną liczbę wiadomości, Skrzynki są kolejkami typu FIFO. Zadanie może przechować wiadomość w skrzynce, Jeżeli zadanie chce przechować w skrzynce a skrzynka jest pełna to zadanie ulega zawieszeniu dopóki w skrzynce będzie dostpny wolny obszar do przechowania wiadomości. Zadanie może pobierać wiadomość ze skrzynki. Jeżeli skrzynka jest pusta a zadanie chce pobrać wiadomość, to zostaje ono zawieszone do momentu, gdy w skrzynce pojawi się wiadomość.

Przesyłanie wiadomości stanowi dodatkową metodę synchronizacji zadań, W odróżnieniu od skrzynek, zadania wysyłające w sposób jawny określają zadanie, które ma ta wiadomość odebrać.

Przydatny link: http://www.kik.pcz.pl/so-add/RTOS/index.htm

Moze sie przydac: :playground:skryptrt.pdf