Wszystkie mechanizmy posiadaja pewne wspolne cechy i podobny
interfejs, co ulatwia zycie programiscie. W przypadku kolejek i semaforow
komunikacja odbywa sie przez pamiec jadra, zas segmenty pamieci dzielonej
sa wspoldzielonymi czesciami wirtualnych przestrzeni adresowych procesow,
co zapewnia wysoka efektywnosc tego mechanizmu komunikacji.
Komunikacja miedzyprocesowa jest pojeciem szerokim, czemu wyraz daje pakiet IPC.
Pozornie rozne mechanizmy: msg -przesylanie komunikatow o konkretnej strukturze,
sem- mechanizm synchronizacji, shm- wspoldzielenie przez procesy pamieci
,zostaly polaczone w jeden pakiet.
Dla kazdego mechanizmu istnieje w przestrzeni adresowej
jadra globalna tablica, opisujaca wszystkie istniejace instancje danego
mechanizmu. Elementami tablic sa struktury (scislej wskazniki do struktur)
zdefiniowane w plikach naglowkowych poszczegolnych mechanizmow. Takze w
plikach naglowkowych sa zdefiniowane rozmiary tych tablic oraz rozmiary
innych elementow danego mechanizmu (np: min i max rozmiar segmentu pamieci
dzielonej).Rozmiary powyzszych tablic w Linuxie 2.0 sa jednakowe dla kazdego
mechanizmu i wynosza 128. Jest to wiec wartosc okreslajaca maksymalna liczbe
instancji danego mechanizmu.
Kazdy mechanizm posiada kilka zmiennych globalnych dla potrzeb statystyki
i kontroli informacji przechowywanej przez dany mechanizm
(np: laczna liczba bajtow wszystkich komunikatow). Zmienne globalne sa
inicjowane na 0. Wskazniki w tablicach inicjalnie wskazuja IPC_UNUSED
zrzutowane na odpowiednia strukture
typowa dla danego mechanizmu.
Kazda instancja ma swoja nazwe - klucz, ktory jest najczesciej liczba typu long. Klucz powinien byc wstepnie uzgodniony pomiedzy procesami, aby ostatecznie korzystaly one z tej samej instancji danego mechanizmu. Klucz jest unikalny w obrebie mechanizmu - instancja musi byc jednoznacznie odszukana przez podlaczajacy sie proces. Wyjatek stanowi klucz IPC_PRIVATE. (def: =0) o ktorym wiecej w punkcie 5. Kazdorazowa zgodnosc kluczy mozna zapewnic definiujac ich wartosci w kodzie aplikacji, co jednak dopuszcza mozliwosc kolizji z kluczem juz istniejacym w systemie. Mozna tez skorzystac z funkcji bibliotecznej ftok:
Key_t jest typem klucza zdefiniowanym domyslnie
jako integer. Wartosc klucza jest generowana przy uzyciu numeru urzadzenia
i numeru i-wezla sciezki podanej jako pierwszy parametr oraz pierwszej
litery projektu podanej jako drugi parametr (dowolna ustalona miedzy procesami
litera). Nalezy zagwarantowac, ze podana sciezka istnieje, inaczej funkcja
zwroci -1. Aby jednak miec pewnosc, ze nie dojdzie do kolizji kluczy, kazda
aplikacja musi podac unikalna sciezke (np: do swojego katalogu domowego),
ta sama dla wszystkich swoich procesow a takze wszystkie klucze w systemie
musza byc uzyskane za pomoca funkcji ftok.
Znak 8-bitowy ,bedacy wartoscia argumentu
proj , funkcja laczy z numerem i-wezla pliku dyskowego oraz z malym numerem
urzadzenia dla tego systemu plikow , w ktorym plik istnieje.Z polaczenia tych trzech
liczb powstaje 32-bitowy klucz. Istnieje szansa (bardzo mala),ze uzywajac dwu
roznych sciezek otrzymamy taka sama wartosc klucza.
Prostszym rozwiazaniem wydaje sie losowe wygenerowanie klucza
i zapisanie go w kodzie aplikacji,jednak wartosc nalezy przekazac innym procesom
np. zapisujac ja na pliku.
Instancja IPC jest identyfikowana przez unikalny w obrebie mechanizmu deskryptor, zwiazany z indeksem tablicy wzorem:
int deskryptor = seq * rozm_tablicy + indeks
gdzie seq jest zmienna globalna mechanizmu typu ushort, zwiekszana o 1 przy kazdym usunieciu dowolnej instancji danego mechanizmu. Tak wiec kolejna instancja utworzona pod tym samym indeksem dostaje deskryptor przynajmniej o rozm_tablicy wiekszy, stary deskryptor traci waznosc. Przyklad:
zwalniamy wejscie w tablicy a nastepnie ponownie przydzielamy to samo:
Zeby stwierdzic, ze deskryptor utracil waznosc musimy
przechowywac w naglowku instancji (strukturze opisujacej instancje) jego
wartosc lub wartosc seq z momentu tworzenia instancji. Oczywiscie, seq
jest krotsze wiec jest przechowywane zamiast deskryptora.
Funkcje systemowe odwoluja sie do tablicy za pomoca deskryptora obliczajac
najpierw indeks:
indeks = deskr mod (rozm_tablicy)
a nastepnie seq:
seq = deskr div (rozm_tablicy)
ktorego wartosc musi byc rowna wartosci zapisanej w naglowku (inaczej deskr jest niewazny i nie uprawnia do dostepu do instancji).
Powyzszy mechanizm przydzielania deskryptorow jest potrzebny,w celu zminimalizowania prawdopodobienstwa odczytywania komunikatow przez proces niepozadany.Uzywajac niewielkich liczb calkowitych mialby szanse natrafic na taka ,ktora jest biezaco uzywanym identyfikatorem majacym ustawione prawo dostepu do czytania dla innych.Jesli wartosciami tych identyfikatorow bylyby male liczby calkowite(np. jak deskryptory plikow),to prawdopodobienstwo znalezienia wlasciwego identyfikatora byloby duze.Najwyzsza pora wyjasnic skad sie biora deskryptory. Otoz kazdy mechanizm pakietu IPC zawiera funkcje systemowa _get mniej wiecej tej postaci:
SYSTEM: int _get (key_t klucz, int flagi)
POWROT: deskryptor nowo utworzonej lub odnalezionej instancji lub
-1
errno:
EACCESS /* brak praw dostepu - przy odszukiwaniu */
EEXIST /* klucz istnieje oraz sa flagi: IPC_CREAT & IPC_EXCL */
EINVAL /* bledne parametry */
ENOENT /* klucz nie istnieje i nie ma flagi IPC_CREAT */
ENOMEM /* brak pamieci */
ENOSPC /* bledny rozmiar - przy tworzeniu */
Funkcja ta pobiera klucz i ewentualne dodatkowe parametry
oraz flagi, oddaje natomiast w zaleznosci od ustawionych flag i efektu
poszukiwan deskryptor instancji o podanym kluczu, nowy deskryptor lub kod
bledu: -1.
Oto przyblizony schemat dzialania funkcji get:
Parametr flagi jest liczba typu int w ktorej poszczegolne bity pierwszych dwoch bajtow oznaczaja prawa dostepu do instancji mechanizmu oraz ustawienie (1) badz brak (0) flag:
IPC_CREAT /*osemkowo: 00001000 prosi o utworzenie
instancji*/
IPC_EXCL /*00002000 blokuje podlaczenie do instancji istniejacej*/
Przypominam, ze int w kompilatorze C Linuxa ma rozmiar
4 bajtow.
Skladania flag dokonuje sie przy pomocy operatora binarnego OR np: (IPC_CREAT |
IPC_EXCL | 0666) oznacza ze wszyscy maja prawa czytania i pisania
(osemkowe 666), instancja o podanym kluczu bedzie utworzona jesli nie istnieje,
jesli natomiast zostala odnaleziona, funkcja get zwroci blad EEXIST (nie
chcemy przeszkadzac komunikujacym sie przez nia procesom).
Warto zwrocic uwage, iz wystepujaca samotnie flaga IPC_EXCL nie
ma zadnego znaczenia.
Po przetlumaczeniu klucza na deskryptor za pomoca funkcji get wszystkie
odwolania do instancji korzystaja z deskryptora, a wiec z punktu widzenia
procesu kllucz nie jest juz potrzebny.
Klucz IPC_PRIVATE (def:=0) wymusza utworzenie nowej instancji
bez wzgledu na to czy klucz 0 juz istnieje czy tez nie. Moze byc wiec kilka
instancji tego samego mechanizmu o kluczu IPC_PRIVATE, ale ich deskryptory
zawsze beda rozne (ich reszty modulo rozm_tablicy oznaczajace indeks slotu
sa rozne).
Struktura naglowkowa kazdego mechanizmu zawiera strukture typu ipc_perm (plik: ipc.h) zawierajaca klucz, prawa dostepu (takie jak dla pliku), identyfikatory uzytkownika i tworcy (inicjalnie te same) oraz ich grup.
IPC_STAT Odzwierciedla stan struktury charakterystycznej dla danego mechanizu IPC_SET Ustawia prawa dostêpu IPC_RMID Usuwa instancje z systemu IPC_INFO Zwraca informacje o parametrach instancjiW przypadku pobierania informacji jadro sprawdza prawa czytania procesu, po czym kopiuje odpowiednie informacje do bufora w przestrzeni adresowej uzytkownika, wskazanego jako parametr wywolania funkcji _ctl. W przypadku modyfikacji stanu instancji prawa pisania procesu nie wystarczaja! Proces musi byc tworca, wlascicielem lub nadzorca. Nie moga byc zmienione informacje o tworcy danej instancji, dzieki czemu zawsze zachowuje on prawa do utworzonego przez siebie obiektu. Prawa czytania nie sa potrzebne dla pobrania informacji globalnych o danym mechanizmie (komenda IPC_INFO).
ipcs - informacje o wszystkich istniejacych instancjach IPC, do ktorych wykonawca ma prawa dostepu
ipcrm <msg | sem | shm> <IPC ID> - usuniecie podanego deskryptora w zakresie podanej instancji (trzeba byc wlascicielem lub tworca).
Wiecej informacji o tych komendach w man-ie
Istnieja pewne podobienstwa mechanizmu IPC do systemu plikow:
get | creat, open |
ctl | unlink |
? | close |
1. Zasadnicza roznica: jadro nie wie jakie procesy maja dostep do mechanizmow IPC, zatem:
- proces ktory nigdy nie wykonal funkcji typu get moze
uzyskac dostep do tych mechanzmow po odgadnieciu deskryptora, jezeli prawa
dostepu beda odpowiednio ustawione.
- struktury IPC nie moga byc automatycznie usuwane przez jadro, poniewaz
nie wiadomo kiedy staja sie one bezuzyteczne.
2. Przestrzen kluczy <=> przestrzen nazw plikow
Przestrzen kluczy jest raczej pomyslana dla srodowiska zlozonego z jednego komputera
ipc.h,
sem.c, msg.c, shm.c, util.c, sem.h, msg.h, shm.h
autor: Dariusz Piotrak