Implementacja monitora w j˛ezyku C++ z wykorzystaniem

Transkrypt

Implementacja monitora w j˛ezyku C++ z wykorzystaniem
Implementacja monitora w j˛ezyku C++ z wykorzystaniem
środowiska PVM
Jakub Gorgolewski, nr indeksu 55456
27 kwietnia 2005
1
Wst˛ep
Celem ćwiczenia było zaimplementowanie monitora realizujacego
˛
podstawowe operacje lock() i unlock(),
umożliwiajacego
˛
współdzielenie danych pomiedzy jego rozproszonymi instancjami oraz wspierajacego
˛
zmienne warunkowe z operacjami wait() i signal(). Komunikacja w środowisku rozproszonym miała być realizowana za pośrednictwem oprogramowania PVM.
2
Algorytm dost˛epu do sekcji krytycznej
Do realizacji bezpiecznego dost˛epu do sekcji krytycznej, jaka˛ jest ciało monitora, wykorzystano zmodyfikowana˛ wersje algorytmu Ricart’a - Agravali. Modyfikacja była potrzebna by zapewnić pełna˛ replikacj˛e
współdzielonych danych. Aby tego dokonać oryginalny algorytm został wzbogacony o dodatkowy typ
wiadomości - potwierdzenie z uaktualnieniem. Wysyłana jest ona przy wychodzeniu z sekcji krytycznej
pod warunkiem, że dane współdzielone zostały zmodyfikowane. Jest ona wysyłana do wszystkich instancji w systemie i zast˛epuje potwierdzenie. W przypadku braku modyfikacji danych współdzielonych,
przy wyjściu z sekcji krytycznej monitor wysyła zwykłe potwierdzenia (tylko do procesów, od których
dostał żadanie
˛
wejścia do sekcji, ale im jeszcze nie wyraził zgody). Takie rozwiazanie daje pełna˛ replikacj˛e danych przy niewielkiej złożoności implementacyjnej i umiarkowanym koszcie komunikacyjnym.
3
Opis implementacji
Ze wzgl˛edu na problemy z obsługa˛ watków
˛
w środowisku PVM monitor został zrealizowany na kilku
odrebnych procesach:
• główny proces aplikacyjny
• proces nadawczy
• porces odbiorczy
Główny proces apliacyjny realizuje dwa watki
˛ przetwarzania: użytkownika i komunikacyjny. Pierwszy
z nich odpowiada za przetwarzanie procesu aplikacyjnego. W momencie wywoływania metod monitora
przez użytkownika informacje o rodzaju metody i jej argumentach przkazywane sa przez kolejke nienazwana˛ do watku
˛ komunikacyjnego. To w watku
˛ komunikacyjnym realizowany jest protokół dost˛epu do
sekcji krytycznej.
Procesy nadawczy i odbiorczy służa˛ jednynie jako interfejsy dla środowiska PVM. Watek
˛ komunikacyjny wymienia z nimi komunikaty, również po przez kolejki nienazwane. Dzieki temu może uniknać
˛
aktywnego czekania na komunikaty, gdyż na deskryptorach kolejek nienazwanych można realizować systemowa˛ funkcj˛e monitorowania stanu poll().
W przypadku wywołań funkcji lock(), unlock() i wait() wymagane jest usypianie watku
˛
użytkownika. Realizowane jest to za pomoca˛ semaforów zaimplementowanych dla watków
˛
POSIX. Semafory te
1
inicjowane sa˛ w stanie opuszczonym, wi˛ec gdy watek
˛ użytkownika musi zostać uśpiony próbuje opuścić
semafor, co powoduje jego zablokowanie dopóki watek komunikacyjny go nie podniesie. Zdecydowano
si˛e na takie rozwiazanie
˛
pozwala ono uniknać
˛ sytuacji wyścigu jaka wystepuj przy zastosowaniu zmiennych warunkowych - kiedy w wyniku niefortunnego przydziału procesora wait() jest wywołane po
signal().
3.1
Klasa CMonitor
Klasa CMonitor zawiera główny kod monitora. Realizuje ona tworzenie dodatkowych procesów i watków.
˛
Ponadto udost˛epnia po przez dziedziczenie chronione nastepujace
˛ metody:
• lock() - wejście do sekcji krytycznej,
• unlock() - wyjście z sekcji krytycznej,
• writeData() - zapis danych współdzielonych,
• readData() - odczyt danych współdzielonych.
3.2
Klasa CConditional
Klasa CConditional jest klasa opakowujac
˛ a˛ interfejs klasy CMonitor w celu realizacji zmiennych warunkowych. Dzieki temu, z punktu widzenia programisty zmienne warunkowe to różne zmienne, a z punktu
widzenia monitora tylko różne identyfikatory. Do poprawnego działania zmienne CConditional musza˛
mieć w konstruktorze przekazany wskaźnik do monitora. Obiekty tej klasy udost˛epniaja˛ nastepujace
˛ publiczne metody:
• wait() - oczekiwanie na zmiennej,
• signal() - obudzenie wszystkich procesów oczekujacych
˛
na zmiennej warunkowej.
Zmienne warunkowe realizowane sa˛ w nast˛epujacy sposób. Do każdej zmienne warunkowej przypisanan
jest osobna grupa rozgłoszeniowa. Wywołanie metody wait() oznacza zapisanie si˛e procesu odbiorcego
do tej grupy i uśpienie watku
˛ użytkownika na wspomnianym wsześniej mechaniźmie semaforów. signal()
sprowadza si˛e do wysłania komunikatu do tej grupy, który w przypadku odebrania powoduje obudzenie
watku
˛ użytkownika. Dla zapewnienia bezpieczeństwa sekcji krytycznej przy wywołaniu metody wait()
monitor wykonuje unlock(), a po obudzeniu lock().
4
Podsumowanie
Do uzyskania pełnej wygody użytkowania zaimplementowanego monitora brakuje jedynie rejestracji i
usuwania nowych instancji monitora w systemie. Póki co liczba instancji podawana jest jako parametr
konstruktora klasy CMonitor.
Obecna implementacja pozwala na zastapienie
˛
środowiska PVM jakimkolwiek środowiskiem zapewniajacym
˛
niezawodna komunikacj˛e kanałami FIFO typu unicast i multicast, a w szczególności implementacja˛
standardu MPI.
2