Do spisu tresci tematu 3

3.2.1 IPC ogolnie




Spis tresci


1.Pakiet IPC

Pakiet IPC SystemuV sklada sie z trzech mechanizmów (typów) komunikacji miedzyprocesowej:

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.


2.Struktury globalne

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.


3.Klucze instancji

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:

LIBRARY: key_t ftok (char* pathname,char proj)
POWROT: wartosc klucza lub -1 w przypadku niepowodzenia

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.


4.Deskryptory instancji

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:

tab_key1.gif

zwalniamy wejscie w tablicy a nastepnie ponownie przydzielamy to samo:

tab_key2.gif

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.

5.Funkcja systemowa _get

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

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:

get.gif

Funkcja wewnetrzna find ( key_t key ) jest odpowiedzialna za wyszukanie indeksu w tablicy glownej ,gdzie przechowywane sa informacje o instancji majcej przydzielony klucz key.

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:

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).


6.Struktura ipc_perm i funkcja systemowa _ctl

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.

perm.gif

Funkcja _ctl( .. , int cmd , ..),

Sterujaca funkcja systemowa ,ktora w zaleznosci od wartosci argumentu cmd> informuje o stanie instancji i pozwala ten stan modyfikowac.Parametrami sa: deskryptor, nazwa operacji i wskaznik do bufora stanu (unia).
Argument cmd moze przyjmowac ponizsze wartosci ( dla trzech mechanizmow ):
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 instancji 
W 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).


7. Komendy shella

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


8. System plikow a IPC

Istnieja pewne podobienstwa mechanizmu IPC do systemu plikow:

1. Zasadnicza roznica: jadro nie wie jakie procesy maja dostep do mechanizmow IPC, zatem:

2. Przestrzen kluczy <=> przestrzen nazw plikow

Przestrzen kluczy jest raczej pomyslana dla srodowiska zlozonego z jednego komputera


9. Bibliografia

  1. ipc.h, sem.c, msg.c, shm.c, util.c, sem.h, msg.h, shm.h
  2. (naglowki funkcji i definicje stalych),
  3. Sven Goldt, Sven van der Meer, Scott Burkett, Matt Welsh: The Linux Programmer's Guide - rozdzial o ipc.
  4. Maurice J. Bach: Budowa systemu operacyjnego UNIX
  5. W. Richard Stevens: Programowanie zastosowan sieciowych w systemie UNIX


autor: Dariusz Piotrak