INT 6. Metody komuni..

Transkrypt

INT 6. Metody komuni..
6. (INT) Metody komunikacji międzyprocesowej w systemach
lokalnych i rozproszonych
Komunikacja międzyprocesowa (Inter-Process Communication – IPC) – nazwa zbioru
sposobów komunikacji pomiędzy wątkami jednego lub wielu procesów. Procesy mogą być
uruchomione na jednym lub wielu komputerach połączonych w sieć. Techniki komunikacji
międzyprocesowej dzielą się na:
• Przenoszenie danych
• Synchronizację
Do zapewnienia komunikacji potrzebne są przynajmniej dwie funkcje interfejsowe – wysyłająca
i odbierająca komunikat:
send(id_odbiorcy, void* bufor, int ile)
receive(id_nadawcy, void* bufor, int ile)
Metody komunikacji międzyprocesowej
Metoda komunikacji
Systemy operacyjne
Systemy
Systemy
lokalne rozproszone
Pliki
Większość systemów
+
+
Sygnały
Wszystkie systemy POSIX
+
-
Gniazdka
Większość systemów
+
+
Kolejki komunikatów
Wszystkie systemy POSIX, Windows
+
-
Łącza nienazwane
Wszystkie systemy POSIX, Windows
+
-
Łącza nazwane
Wszystkie systemy POSIX, Windows
+
-
Semafory
Wszystkie systemy POSIX, Windows
+
-
Pamięć współdzielona
Wszystkie systemy POSIX, Windows
+
-
Zmapowany plik w pamięci
Wszystkie systemy POSIX, Windows
+
+
Przekazywanie
komunikatów
System z zaimplementowaną obsługą
MPI, Java RMI, CORBA, RPC, ...
+
+
UWAGA: Wszystkie funkcje opisywane poniżej odnoszą się do systemu UNIX.
Pliki – plik może zostać otwarty w kilku procesach. Pojawia się tutaj problem spójności danych
i wspólnego dostępu. Plik może być w jednej chwili odczytywany przez wiele procesów, ale
zapisywać może tylko jeden proces w danej chwili. Po zapisie dane w innych procesach
pozostają nieaktualne, jeśli zostały wczytane przed zapisanie pliku przez inny proces.
Komunikacja może zachować w obrębie jednego systemu operacyjnego lub też pomiędzy
kilkoma różnymi systemami, które współdzielą przestrzeń dyskową.
Funkcje:
• fopen() - otwarcie pliku
• fwrite() - zapis do pliku
• fread() - odczyt z pliku
• fclose() - zamknięcie pliku
Sygnały (POSIX) – asynchroniczne powiadomienia wysyłane do procesów będące reakcją na
zaistniałe wydarzenia. Kiedy do procesu wysłany zostanie sygnał, przerwanie systemu
operacyjnego przerywana normalny bieg. Wykonywanie może zostać przerwane podczas
trwania jakiejkolwiek nieatomowej operacji. Jeśli proces posiadał wcześniej ustalone funkcje
obsługi sygnałów, to zostaje wykonana właściwa funkcja. W przeciwnym wypadku wykonywana
jest domyślna obsługa sygnałów. Każdy sygnał z wyjątkiem SIGKILL i SIGSTOP można
przechwycić. Sygnały obsługiwane są tylko przy przejściu między trybem jądra systemu a
trybem użytkownika.
Funkcje:
• signal() - rejestruje funkcję obsługi sygnału
• sigset() - j/w
• kill() - wysłanie sygnału
Gniazdka – reprezentują dwukierunkowy punkt końcowy połączenia, co oznacza możliwość
przyjmowania i wysyłania danych. W systemie UNIX gniazdko traktowane jest jak deskryptor
otwartego pliku (można używać funkcji read(), write(), close()). Gniazdko tworzone jest za
pomocą funkcji socket().Przed użyciem należy nadać mu adres funkcją bind().
Identyfikatorem konkretnego połączenia jest 5 atrybutów: adres odbiorcy, port odbiory, adres
nadawcy, port nadawcy i rodzaj protokołu (TCP lub UDP). Dzięki niemu można jednoznacznie
zidentyfikować połączenie.
Funkcje:
• socket() - utworzenie gniazdka
• bind() - nadanie gniazdku adresu
• connect() - przypisanie adresu drugiej strony
• listen() - nasłuchiwanie na gniazdku
• write(), send(), sendto() - zapis do gniazdka
• read(), recv(), recvfrom() - odczyt z gniazdka
• close() - zamknięcie gniazdka
Kolejki komunikatów – są to listy jednokierunkowe zawierające komunikaty o określonym
maksymalnym rozmiarze. Nowe komunikaty dodawane są na koniec listy, przez co zachowana
jest kolejność ich wysyłania. Każdy komunikat ma parametr zwany typem, co pozwala na
obsługę kilku „strumieni” komunikatów w ramach jednej kolejki.
Funkcje:
• msgget() - tworzenie kolejki komunikatów
• msgsnd() - wysyłanie komunikatu
• msgrcv() - odbieranie komunikatu
• msgctl() - usuwanie (jeśli ustawimy w parametrze cmd flagę IPC_RMID)
Łącza nienazwane – zwane też strumieniami pipe, pozwalają łączyć spokrewnione ze sobą
procesy (rodzic - dziecko). Transmisja jest jednokierunkowa i z reguły łączy ona wyjście stdout
jednego procesu z wejściem stdin drugiego. Łącza nienazwane tworzone są funkcją pipe(int
fd[2]), która wypełnia dwuelementową tablicę deskryptorów. Deskryptor fd[0] jest końcem
otwartym do czytania, a fd[1] do pisania. Oba końce traktowane są w UNIXie jak zwykłe
deskryptory plików (można używać funkcji read(), write(), close()). Ponadto jądro systemu
gwarantuje, że operacje zapisu nie przekraczające rozmiaru strumienia są niepodzielne.
Strumień pipe jest buforem wielkości 4kB.
Funkcje:
• pipe() - tworzenie łącza nienazwanego
• dup(), dup2() - tworzenie strumieni stdin-stdout (kopiowanie deskryptorów)
• write() - zapis do łącza
• read() - odczyt z łącza
• close() - zamknięcie łącza
Łącza nazwane – zwane też strumieniami FIFO, mogą być używane przez procesy nie
spokrewnione ze sobą, a nawet przez procesy zupełnie różnych użytkowników. Posiadają one
dowiązanie w systemie plików i są tworzone funkcją mknod() lub komendą mknod w UNIXie.
Funkcja open() używana do otwarcia łącza do zapisu blokuje proces, aż do mementu otwarcia
kolejki do odczytu i odwrotnie. Kolejki FIFO mają z reguły większy rozmiar bufora (4-16kB).
Funkcje:
• mknod() - tworzenie łącza nazwanego
• open() - otwieranie łącza do pisania lub czytania
• write() - zapis do łącza
• read() - odczyt z łącza
• unlink() - usuwanie łącza
Łącza
•
•
•
•
•
nazwane i nienazwane mają wiele podobieństw:
zamknięcie końca do pisania generuje u czytelników EOF
zamknięcie końca do czytania generuje sygnał SIGPIPE wysyłany do wszystkich pisarzy
zapis i odczyt przez standardowe funkcje read() i write()
niepodzielność zapisów mniejszych niż rozmiar strumienia
blokowanie procesów w przypadku przepełniania lub pustego bufora
Semafory – abstrakcyjne typy danych, które stanowią klasyczną metodę kontroli dostępu do
wspólnego zasobu. Na semafor składa się zmienna i kolejka procesów. Semafor może być
binarny (zmienna przyjmuje tylko wartości 0 i 1) lub ogólny (zmienna nieujemna). Na
semaforze można wykonywać 2 typy operacji:
• zajmij(S)
jeśli S > 0, to S-- i idź dalej,
jeśi S = 0, to umieść proces w kolejce oczekujących na zwolnienie semafora i zaśnij
• zwolnij(S)
jeśli kolejka oczekujących jest pusta, to S++,
jeśli ktoś czeka, to usuń go z kolejki oczekujących i obudź go, nie zmieniając wartości S
Bieżąca wartość semafora odpowiada liczbie wolnych zasobów. Osiągnięcie wartości 0 oznacza,
że kolejny proces żądający zasobu zostanie uśpiony. Możliwe jest zmniejszanie lub zwiększanie
semafora o wartość inną niż 1, o ile nie doprowadzi to do osiągnięcia wartości ujemnej.
Funkcje:
• semget() - tworzenie semafora
• semctl() - usuwanie semafora (jeśli ustawimy w parametrze cmd flagę IPC_RMID)
• semop() - zwalnianie i zajmowanie semafora
◦ parametr sem_op < 0 – zajęcie semafora
◦ paramert sem_op > 0 – zwolnienie semafora
◦ parametr sem_op = 0 – synchronizacja z semaforem (czekanie aż osiągnie 0)
Pamięć współdzielona – jest specjalnie utworzonym segmentem wirtualnej przestrzeni
adresowej, do którego dostęp może mieć wiele procesów. W zależności od praw dostępu
procesy mogą odczytywać i/lub zapisywać wartości w pamięci współdzielonej, przy czym w
przypadku współbieżnie działających procesów konieczne jest najczęściej synchronizowanie
dostępu np. za pomocą semaforów. Aby używać pamięci współdzielonej do komunikacji każdy
proces musi najpierw wykonać funkcję shmget(), która utworzy lub znajdzie istniejący
segment pamięci, a następnie znaleziony segment przypisać do swojej przestrzeni adresowej
funkcją shmat().
Funkcje:
• shmget() - utworzenie segmentu pamięci wspólnej lub znalezienie już istniejącego
• shmctl() - usuwanie segmentu pamięci (parametr cmd musi mieć ustawioną flagę
IPC_RMID)
• shmat() - dołączenie segmentu pamięci do przestrzeni adresowej procesu
• shmdt() - odłączenie segmentu pamięci od przestrzeni adresowej procesu
Zmapowany plik w pamięci – możliwy jest dostęp do otwartych plików tak, jakby
znajdowały się one w pamięci RAM, tzn. zamiast poruszać się po pliku za pomocą fseek() i
pisać/czytać przez fwrite()/fread(), można używać wskaźników i zwykłych operacji przypisania.
Pozwala na to funkcja mmap():
void *mmap(void *addr, size_t len, int prot, int flags, int filedes, off_t off);
Funkcje:
• mmap() - mapuje plik w pamięci RAM
Przekazywanie komunikatów – na to zagadnienie składają się takie technologie jak RPC,
MPI, Java RMI oraz wszystkie inne tego typu. Ogólna idea jest taka, że jeden z komputerów
dostaje zlecenie zrealizowania określonego zadania. Od użytej technologii zależy, czy podzieli
on to zadanie na kilka mniejszych i zleci ich realizację do innych komputerów, od których
potem odbierze wyniki (MPI), czy też wywoła funkcję na innej maszynie o większej mocy, która
szybciej wykona to zadanie (RPC).
wszystkie obrazki pochodzą z pozycji [1]
Literatura:
przede wszystkim:
[1] T. Surmacz, wykład z SSO http://infeka.wroclaw.pl/!archiwum/ssou1/Sieciowe
%20systemy%20operacyjne%20UNIX/WYKLAD.PDF [PL]
a, poza tym:
[2] J. Ułasiewicz, wykłady z Programowania Współbieżnego i Rozproszonego,
http://jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/Progr-Wspol-i-Rozprosz/wyklad/SystRozprWstep13.pdf [PL]
[3] J. Ułasiewicz, wykłady z Programowania Współbieżnego,
http://jedrzej.ulasiewicz.staff.iiar.pwr.wroc.pl/ProgramowanieWspolbiezne/wyklad/Komuni
kacjaWstep2.pdf [PL]
[4] http://pl.wikipedia.org/wiki/Komunikacja_mi%C4%99dzyprocesowa [PL]
[5] http://en.wikipedia.org/wiki/Inter-process_communication [EN]
[6] http://en.wikipedia.org/wiki/Signal_(computing) [EN]
[7] http://www.cs.put.poznan.pl/akobusinska/downloads/pamiec_wspoldzielona.pdf [PL]

Podobne dokumenty