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