Programowanie współbieżne i rozproszone/PWR Ćwiczenia koleki

Z Studia Informatyczne
Wersja z dnia 14:03, 16 paź 2006 autorstwa Mengel (dyskusja | edycje)
(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)
Przejdź do nawigacjiPrzejdź do wyszukiwania

Tematyka zajęć

Omówienie mechanizmów kolejek komunikatów z pakietu IPC.

Literatura

  • M.J.Rochkind, Programowanie w systemie Unix dla zaawansowanych, rozdz. 7.5
  • strony man dotyczące poszczególnych funkcji systemowych
  • W.R. Stevens, Programowanie zastosowan sieciowych w systemie Unix, rozdz. 3.8, 3.9

Scenariusz zajęć

Mechanizm kolejek

Kolejki komunikatów są jednym z trzech mechanizmów komunikacyjnych tworzących tak zwany pakiet IPC Systemu V. Poza kolejkami komunikatów należą do niego semafory oraz pamięć dzielona.

Podstawowe funkcje systemowe przeznaczone do obsługi kolejek to:

  • msgget --- służy do tworzenia/otwierania kolejki
  • msgctl --- służy do sterowania kolejka komunikatow, w szczególności pozwala zlikwidować kolejkę
  • msgsnd --- służy do wysyłania komunikatów
  • msgrcv --- służy do odbierania komunikatów

Otwieranie kolejki

Aby było możliwe skorzystanie z kolejki komunikatów jest konieczne jej utworzenie albo uzyskanie dostępu do kolejki istniejacej. W obydwu przypadkach stosuje się funkcję msgget, analogicznej do funkcji open używanej w przypadku plików.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(klucz, flagi)                       /* pobierz identyfikator */
key_t klucz;                                   /* klucz kolejki */
int flagi;                                     /* opcje */

Funkcja ta pobiera klucz, który powinien być długą liczbą całkowitą i przekazuje w wyniku identyfikator kolejki (albo -1 w przypadku błędu).

Klucz jest nazwą kolejki komunikatów i pełni rolę podobną do nazwy pliku w operacjach na plikach. Procesy, które chcą korzystać z tej samej kolejki komunikatów muszą ją otworzyć funkcją msgget z tą samą wartością pierwszego parametru. W wyniku funkcji msgget otrzymujemy identyfikator kolejki. Jest on odpowiednikiem deskryptora pliku i wykorzystuje się go we wszystkich pozostałych operacjach na kolejce komunikatów.

Warto przy okazji zwrócić uwagę na istnienie funkcji ftok (por. man), która może by pomocna przy tworzeniu klucza.

Parametr flagi funkcji msgget odpowiada drugiemu i trzeciemu argumentowi funkcji open łącznie 9 mniej znaczących jego bitów określa prawa dostepu do kolejki, w sposob analogiczny jak dla funkcji open - prawa czytania i pisania mają znaczenie zgodne z intuicją natomiast prawo wykonywania nie jest używane.

Standardowo funkcja msgget powoduje odszukanie kolejki komunikatów o podanym kluczu i przekazanie w wyniku jej identyfikatora. Jeśli kolejki o wskazanym kluczu nie ma, to wynikiem jest błąd. Kolejki komunikatów znajdują się w pamięci systemowej. Listę istniejących kolejek komunikatów można obejrzeć wykonując z linii poleceń polecenie ipcs.

Tworzenie kolejki komunikatów

Fizyczne utworzenie kolejki komunikatow nastepuje po wykonaniu msgget, w ktorej bit IPC_CREAT w parametrze 'flagi' jest ustawiony. Powoduje to utworzenie kolejki komunikatow o podanym kluczu, jesli jeszcze nie istniala lub po prostu przekazanie w wyniku identyfikatora istniejacej kolejki komunikatow. Zatem jest to najbardziej uniwersalne wywolanie funkcji msgget.

Czasami zachodzi potrzeba wykonania pewnych czynnosci przy tworzeniu kolejki komunikatow (np.: umieszczeniu w niej jakis komunikatow). Przydatna jest wtedy flaga IPC_EXCL stosowana w polaczeniu z IPC_CREAT. Funkcja msgget usiluje wtedy utworzyc kolejke komunikatow o podanym kluczu, jesli sie to uda, to przekazuje w wyniku identyfikator utworzonej kolejki, w przeciwnym razie konczy sie z bledem. Mozna w ten sposob w niepodzielny sposob sprawdzic istnienie kolejki komunikatow i ja ewentualnie utworzyc.

Jesli klucz ma wartosc IPC_PRIVATE nowa kolejke tworzy sie niezaleznie od ustawienia bitu IPC_CREAT.

        • Przeczytaj man msgget


Do wysylania i odbierania komunikatow sluza funkcje 'msgsnd' i 'msgrcv'. Obie te funkcje jako drugi argument przyjmuja wskaznik na strukture dowolnego typu zawierajaca odpowiednio wysylany/odbierany komunikat. Jedyne ograniczenie to koniecznosc wystepowania na poczatku tej struktury dlugiej liczby calkowitej wiekszej od zera, ktora nazywa sie rodzajem komunikatu. Wprowadzenie pojecia rodzaju komunikatu pozwala odbiorcy na wybor z kolejki komunikatow wlasciwego rodzaju oraz oczekiwanie na taki komunikat.

int msgsnd(idk, buf, lbajt, flagi) /* przeslij komunikat */ int idk; /* identyfikator kolejki */ struct msgbuf *buf; /* wskaznik do komunikatu */ int lbajt; /* dlugosc komunikatu */ int flagi;

Funkcja zwraca -1 w przypadku bledu i 0 w przypadku sukcesu. Dlugosc komunikatu oznacza liczbe bajtow komunikatu bez pola okreslajacego rodzaj.

Parametr flagi ma zwykle wartosc 0. Powoduje to wstrzymanie procesu w przypadku przepelnienia kolejki. Po ustaniu przepelnienia proces jest kontynuowany. Wartosc IPC_NOWAIT flagi powoduje natychmiastowe zakonczenie funkcji z okreslonym kodem bledu (errno ustawiane na EAGAIN).

        • Przeczytaj man msgsnd

int msgrcv(idk, buf, lbajt, typkom, flagi) /* odbierz komunikat */ int idk; struct msgbuf *buf; int lbajt; long typkom; int flagi;

Funkcja zwraca liczbe otrzymanych bajtow lub -1 w przypadku bledu. Argument 'lbajt' okresla maksymalna liczbe bajtow, ktora mozna umiescic w buforze 'buf' (znowu bez bajtow okreslajacych rodzaj komunikatu.

Za pomoca msgrcv mozemy wyberac komunikaty z kolejki. I tak: jesli typkom = 0, to z kolejki odczytywany jest pierwszy komunikat dowolnego typu. Jesli natomiast typkom > 0, to wtedy odczytywany jest pierwszy komunikat o typie typkom. Ustawienie parametru 'flagi' na 0 powowduje zawieszenie procesu w oczekiwaniu na (wlasciwy) komunikat. Ustawienie wartosci IPC_NOWAIT powoduje ewentualne zakonczenie funkcji z odpowiednim bledem.

Istnieje ponadto mozliwosc odczytania z kolejki komunikatow pierwszego komunikatu o rodzaju roznym od wskazanego oraz wyboru pierwszego komunikatu o najmniejszym rodzaju sposrod mniejszych od wskazanego (wybor priorytetowy).

        • Przeczytaj man msgrcv

Kolejna funkcja zwiazana z komunikatami jest funkcja 'msgctl'. Umozliwia ona dostep do struktury jadra przechowujacej informacje o kolejce. Najwazniejsza z naszego punkt widzenia operacja mozliwa do przeprowadzenia za pomoca tej funkcji jest zlikwidowanie kolejki.

int msgctl(idk, polec, bufst) /* sterowanie kolejka */ int idk; int polec; /* polecenie */ struct msqid_s *bufst; /* wskaznik do bufora stanu */

Funkcja zwraca 0 w przypadku sukcesu i -1 w przypadku bledu. Polecenie usuwajace kolejke ma postac IPC_RMID. Odpowiednia postac wywolania to:

      msgctl(idk, IPC_RMID, NULL)
        • Przeczytaj man msgctl

Pliki naglowkowe do omawianychi funkcji znajduja sie w zbiorze: <sys/msg.h>.

W pliku <sys/ipc.h> zdefiniowana jest ponadto struktura ipc_perm, w ktorej jadro przechowuje informacje o tworcy, wlascicielu, trybach dostepu, numerze kolejnym i kluczu kolejki.

Jest ona elementem struktury msqid_ds, ktora ponadto zawiera takie informacje jak wskazniki do pierwszego i ostatniego komunikatu znajdujacego sie aktualnie w kolejce, liczba bajtow w kolejce, liczba komunikatow w kolejce, pojemnosc kolejki, identyfikatory procesow, ktore ostatnio pisaly i czytaly do/z kolejki, czasy ostatniego wykonania tych operacji oraz czas ostatniego wywolania msgctl.


Bezposredni dostep do pol tej struktury daje funkcja msgctl.

Osoby zainteresowane wykorzystywanymi przez jadro strukturami danych uzywanymi do przechowywania informacji o kolejkach odsylam do ksiazki W.R.Stevensa, rozdz. 3.8 i 3.9

===============================================================

2. Programy przykladowe:

 a) `msgtool' - bardzo prosty program umozliwiajacy wyslanie i odebranie
    komunikatu, stworzenie, skasowanie kolejki i zmiane praw dostepu.
    Przed uruchomieniem trzeba ustawic zmienna srodowiskowa MSGKEY np.:
      export MSGKEY=4321
 b) `msgsrv' i `msgcli' - programy umozliwiajace przesylanie plikow przez 
    kolejki komunikatow. 
    Nalezy uruchomic `msgsrv' na jednej konsoli, a `msgcli' na drugiej.
    Zakonczenie `msgsrv': ctrl-C. `msgcli' pobiera nazwe pliku z stdin.
    Programy te maja zdefiniowany klucz w pliku 'mesg.h'.
 c) `limits' sprawdza pojemnosc kolejki: maksymalna wielkosc
    komunikatu i ilosc pamieci przeznaczona na komunikaty.


3. Pliki zawieraja zrodla programow przykladowych. Postaraj sie zrozumiec ich

  dzialanie.
  err.c, err.h

Obsluga bledow

  msgtool.c
  	Program demonstrujacy operacje na kolejkach komunikatow
  mesg.h
  	Plik naglowkowy dla `msgsrv.c' i `msgcli.c'. Definicja komunikatu

i klucza kolejki.

  msgsrv.c
       Serwer sluzacy do wysylania plikow. W petli odbiera nazwy plikow 

od klientow i przesyla te pliki klientom. Przechwytuje SIGINT, ktorego wywolanie powoduje zakonczenie programu.

  msgcli.c
       Klient czyta z wejscia nazwe pliku i wysyla serwerowi. Odebrany

plik wypisuje na stdout.

  limits.c
  	Badanie ograniczen systemu: maksymalnego rozmiaru komunikatu

i pojemnosci kolejki. Przyklad uzycia flagi IPC_PRIVATE. Ograniczenia te sa zawarte w Linuxie w pliku /usr/include/linux/msg.h

4. Kompilacja: wywolaj program `make':

  do dyspozycji sa dwa pliki dla programu make: 
  - Makefile - plik podstawowy o budowie analogicznej jak na poprzednich 
    zajeciach, oraz dla osob zainteresowanych
  - Makefile.new - funkcjonalanie rownowazny plik 'uniwersalny'. 
  Wywolanie make bez parametrow spowoduje oczywiscie uzycie pierwszego z 
  tych plikow.   


5. Porzadki:

 Poniewaz kolejki komunikatow moga istniec rowniez po zakonczeniu procesow,
 ktore je stworzyly i z nich korzystaly niepotrzebne kolejki wymagaja
 jawnego usuniecia. Na poziomie shella mozliwe jest wykorzystanie
 programu 'ipcs' do sprawdzenia, jakie kolejki w systemie istnieja
 oraz ewentualne wykorzystanie programu 'ipcrm' do usuniecia niepotrzebnych 
 kolejek.  Na zakonczenie laboratorium nalezy sprawdzic, czy nie zostawiamy
 niepotrzebnych kolejek.
 Na poziomie programu wygodnym narzedziem do sprzatania utworzonych 
 kolejek sa funkcje obslugi sygnalow.

6. Uwagi:

=

 a) Dla chetnych Makefile.new w nowym stylu.
 b) Uwaga na prawa dostepu: jesli nie bedzie praw do czytania program
    ipcs nie pokaze nam kolejki. (ale mimo to da sie ja skasowac ipcrm)
 c) Program ipcs moze byc uzyteczny rowniez do sledzenia efektow
    dzialania programu 'msgtool'.
    

7. Cwiczenie:

==

Jak moze zauwazyles analizujac tresc programow serwera i klienta uruchomienie jednoczesne dwoch klientow `msgcli' moze spowodowac 'przemieszanie sie' przesylanych plikow, poniewaz wszyscy klienci czytaja komunikaty o tym samym identyfikatorze (rownym 2).

Twoje zadanie polega na napisaniu serwera, ktory realizuje na zlecenie proste dzialania arytmetyczne (dodawanie, odejmowanie, mnozenie) na liczbach calkowitych oraz klienta, ktory korzysta z jego uslug. Serwer otrzymuje od klientow komunikaty zawierajace dwie liczby calkowite oraz znak okreslajacy rodzaj dzialania a odsyla wynik. Komunikacja powinna gwarantowac odeslanie wyniku wlasciwemu zleceniodawcy.