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

From Studia Informatyczne

Spis treści

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 komunikatów następuje po wykonaniu msgget, w której bit IPC_CREAT w parametrze flagi jest ustawiony. Powoduje to utworzenie kolejki komunikatów o podanym kluczu, jeśli jeszcze nie istniała lub po prostu przekazanie w wyniku identyfikatora istniejącej kolejki komunikatów. Zatem jest to najbardziej uniwersalne wywołanie funkcji msgget.

Czasami zachodzi potrzeba wykonania pewnych czynności przy tworzeniu kolejki komunikatów (np.: umieszczeniu w niej jakiś komunikatów). Przydatna jest wtedy flaga IPC_EXCL stosowana w połączeniu z IPC_CREAT. Funkcja msgget usiłuje wtedy utworzyć kolejkę komunikatów o podanym kluczu i jeśli się 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.

Struktura komunikatu

Komunikatem jest struktura dowolnego typu. Wysyłany komunikat jest elementem tej struktury. Przed nim jednak musi wystąpić pole typu long. Zawiera ono, tzw. typ komunikatu. Typ wysyłanego komunikatu powinien być liczbą całkowitą większą od zera.


Wysyłanie komunikatów

Do wysyłania komunikatów służy funkcja msgsnd.

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 przekazuje w wyniku -1 w przypadku błędu i 0 w przypadku sukcesu. Długość komunikatu oznacza liczbę bajtów komunikatu bez pola okreslającego typ.

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

Odbieranie komunikatów

Do odbierania komunikatów służy funkcja systemowa msgrcv:

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

Funkcja zwraca liczbę 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 wybierac komunikaty z kolejki. I tak:

  1. Jesli typkom = 0, to z kolejki odczytywany jest pierwszy komunikat dowolnego typu.
  2. Jesli 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 i o najmniejszym rodzaju sposrod mniejszych od wskazanego (wybor priorytetowy).

Usuwanie kolejki komunikatów

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)


Przykłady

  • msgtool.c --- program umożliwiający wysyłanie i odebranie komunikatu, stworzenie, skasowanie kolejki i zmiane praw dostepu. Przed uruchomieniem trzeba ustawic zmienna srodowiskowa

MSGKEY np.:

export MSGKEY=4321
  • msgsrv.c oraz msgcli.c --- 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.


Uwagi

  1. Poniewaz kolejki komunikatow moga istniec rowniez po zakonczeniu procesow, ktore je stworzyly i z nich korzystaly niepotrzebne kolejki wymagaja jawnego usuniecia.
    1. 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.
    2. Na poziomie programu wygodnym narzedziem do sprzatania utworzonych
 kolejek sa funkcje obslugi sygnalow.
  1. Uwaga na prawa dostepu: jesli nie bedzie praw do czytania program ipcs nie pokaze nam kolejki. (ale mimo to da sie ja skasowac ipcrm)
  2. Program ipcs moze byc uzyteczny rowniez do sledzenia efektow dzialania programu 'msgtool'.