KOLEJKI KOMUNIKATÓW IPC

Podobne dokumenty
Programowanie Współbieżne. Komunikacja między procesowa IPC

IPC: Kolejki komunikatów

Mechanizmy z grupy IPC

Shared memory and messages. Functions. process 0. process 1. program 0. program 0. data 0. data 1. program 1. data 0. data 1.

Temat zajęć: Mechanizmy IPC: kolejki komunikatów.

Pamięć współdzielona

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

1. Utwórz blok pamięci współdzielonej korzystając z poniższego kodu:

Instytut Teleinformatyki

Mechanizmy z grupy IPC

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Semafory, pamięć dzielona i kolejki komunikatów

Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

Opis protokołu RPC. Grzegorz Maj nr indeksu:

Obsługa plików. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 25 września 2011

int tab[5]; tab[1]; ciągły obszar pamięci, w którym umieszczone są elementy tego samego typu macierz [ ] - dwuargumentowy operator indeksowania

Pliki. Informacje ogólne. Obsługa plików w języku C

Kolejki komunikatów POSIX

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

Pamięć dzielona i kolejki komunikatów

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

SYSTEMY CZASU RZECZYWISTEGO - VxWorks

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

Struktury. Przykład W8_1

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

Wykład X. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2016 Janusz Słupik

2 Przygotował: mgr inż. Maciej Lasota

4.2 Sposób korzystania z l acza

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

Funkcje zawarte w bibliotece < io.h >

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Procesy. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 9 października 2011

1. Kolejki komunikatów POSIX

Biblioteka standardowa - operacje wejścia/wyjścia

Funkcje zawarte w bibliotece < io.h >

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Gniazda BSD. komunikacja bezpołączeniowa

Linux Kernel III. Character devices

Pliki. Informacje ogólne. Obsługa plików w języku C

Funkcja (podprogram) void

Komunikacja za pomocą potoków. Tomasz Borzyszkowski

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Uzupełnienie dot. przekazywania argumentów

Aplikacja Sieciowa wątki po stronie klienta

problemu producenta i konsumenta z ograniczonym buforem cyklicznym. Wszystkie funkcje dotyczace

Zmienne, stałe i operatory

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Programowanie I C / C++ laboratorium 03 arytmetyka, operatory

PARADYGMATY PROGRAMOWANIA Wykład 4

Systemy Operacyjne - Operacje na plikach

Programowanie Proceduralne

Wykład 1

Wstęp do programowania 1

Kolejki FIFO (łącza nazwane)

SYSTEMY OPERACYJNE I laboratorium 3 (Informatyka stacjonarne 2 rok, semestr zimowy)

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

Szablony klas, zastosowanie szablonów w programach

Podstawy programowania w języku C++

KURS C/C++ WYKŁAD 7. struct Punkt { int x, y; int kolor; };

Tablice, funkcje - wprowadzenie

Architektura typu klient serwer: przesyłanie pliku tekstowo oraz logowania do serwera za pomocą szyfrowanego hasła

Lab 10. Funkcje w argumentach funkcji metoda Newtona. Synonimy nazw typów danych. Struktury. Tablice struktur.

UŻYCIE I ZARZĄDZANIE WĄTKAMI

Struktury czyli rekordy w C/C++

ŁAŃCUCHY W JĘZYKU C/C++

UŻYCIE I ZARZĄDZANIE WĄTKAMI

Szablony. Szablony funkcji

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

Funkcje jadra systemu operacyjnego UNIX

Wykład 7 Abstrakcyjne typy danych słownik (lista symboli)

Programowanie Współbieżne. W Linuxie/Unixie

Języki i techniki programowania Ćwiczenia 2

Funkcje jadra systemu operacyjnego UNIX

Podstawy programowania skrót z wykładów:

Podstawy programowania 1

13. Kolejki komunikatów POSIX

Wartości domyślne, przeciażenia funkcji

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

/* dołączenie pliku nagłówkowego zawierającego deklaracje symboli dla wykorzystywanego mikrokontrolera */ #include <aduc834.h>

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Krótki kurs programowania współbieżnego (2)

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

ang. file) Pojęcie pliku (ang( Typy plików Atrybuty pliku Fragmentacja wewnętrzna w systemie plików Struktura pliku

Tablice deklaracja, reprezentacja wewnętrzna

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Języki i metodyka programowania. Wprowadzenie do języka C

Operatory. Operatory bitowe i uzupełnienie informacji o pozostałych operatorach. Programowanie Proceduralne 1

System plików warstwa logiczna

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Transkrypt:

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Współbieżność procesów (czy wątków) wiąże się często z potrzebą okresowej (asynchronicznej) wymiany komunikatów. Żaden z omawianych wcześniej mechanizmów nie spełniłby się najlepiej w tej roli. Po raz pierwszy problem ten znalazł rozwiązanie w UNIX System V w postaci kolejki komunikatów, ang. message queues wprowadzonym jeszcze przez AT&T w roku 1983, a stosowanych do chwili obecnej w rodzinie systemów nawiązujących po spuścizny UNIX. Kolejki komunikatów stanowią jeden z kilku elementów funkcjonalnych tworzących InterProcess Communication, IPC implementowany standardowo w obrębie jądra systemów będących potomkami UNIX System V. Również MsWindows, którego twórcy mają od pewnego czasu aspiracje stworzenie systemu wspierającego współbieżność dysponuje także swoistym IPC. Kryspin Mirota, kmirota@ath.bielsko.pl 1

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Kolejka komunikatów stanowi połączona listę wiadomości przechowywanych w obszarze pamięci jądra systemowego i jest identyfikowana przez unikalny klucz identyfikator qmsqid (queue identifier) będący nieujemną liczbą całkowitą. Z poziomu interface'u użytkownika informacja o istniejących kolejkach komunikatów może być pobrana poleceniem $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x0000000a 0 kmirota 777 0 0 $ Kolejka komunikatów może być usunięta z obszaru pamięci jądra poleceniem $ ipcrm [-Q msgkey] [-q msgid] W pokazanym wcześniej wyniku polecenia ipcs byłoby to $ ipcrm -Q 0x0000000a lub $ ipcrm -q 0 Kryspin Mirota, kmirota@ath.bielsko.pl 2

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Celem obsługi tego sposobu komunikacji, w obszarze pamięci jadra tworzona jest tablica kolejek msgque[] o rozmiarze (maksymalnym) MSGMNI, której elementem składowym są struktury o definicji (w linux/msg.h) struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; /*pierwszy komunikat w kolejce*/ struct msg *msg_last; /*ostatni komunikat w kolejce*/ kernel_time_t msg_stime; /*czas ostatniego msgsnd*/ kernel_time_t msg_rtime; /*czas ostatniego msgrcv*/ kernel_time_t msg_ctime; /*czas ostatniej zmiany*/ struct wait_queue *wwait; struct wait_queue *rwait; unsigned short msg_cbytes; /*liczba bajtów w kolejce*/ unsigned short msg_qnum; /*liczba komunikatów w kolejce*/ unsigned short msg_qbytes; /*maksymalna liczba bajtow w kolejce*/ kernel_ipc_pid_t msg_lspid; /*pid ostatniego msgsnd() */ kernel_ipc_pid_t msg_lrpid; /*pid ostatniego msgrcv() */ }; Tablica ta jest indeksowana za pośrednictwem identyfikatora danej kolejki qid. Zauważmy, że Struktura ta zawiera w szczególności wskazania, w postaci msg_first i msg_last identyfikujące listę komunikatów powiązanych z daną kolejką. Kryspin Mirota, kmirota@ath.bielsko.pl 3

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Nowa kolejka jest tworzona, co wiąże się z "dopisaniem" do tablicy msgque struktury msqid_ds a jeżeli już istnienie, to jest otwierana celem uzyskania dostępu wywołaniem funkcji msgget(). SYNOPSIS #include <sys/msg.h> int msgget( key_t key, int flag ); key_t key predefiniowana stała IPC_PRIVATE (jeżeli( kolejka prywatna) albo unikalny klucz jeżeli ma być dostępna publicznie (w w pierwszym przypadku klucz wygeneruje jądro systemowe) int flag zwykle IPC_CREAT polecająca utworzyć kolejkę (o o ile nie istnieje) RETURN int indeks msqid do tablicy kolejek msgque. identyfikujący w niej strukturę msqid_ds ERRORS -1 Kryspin Mirota, kmirota@ath.bielsko.pl 4

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Składowe msqid_ds do której funkcja zwróciła indeks inicjowane są w taki sposób że: msg_perm.cuid i msg_perm.uid oraz odpowiednio msg_perm.cgid i msg_perm.gid inicjowane są wartościami identyfikatora właściciela procesu oraz jego grupy; na pozycję 9 najmniej znaczących bitów pola msg_perm.mode jest kopiowanych z 9 najmniej znaczących bitów wartości aktualnej parametru formalnego msgflg, przy czym ipc_perm jest zdefiniowane w ogólności jako struct ipc_perm { key_t key; /* key wysłany przez msgget() */ uid_t uid; /* UID właściciela */ gid_t gid; /* GID grupy właściciele */ uid_t cuid; /* UID twórcy */ gid_t cgid; /* GID grupy twórcy */ unsigned short mode; /* uprawnienia */ unsigned short seq; /* numer sekwencyjny */ }; msg_qnum, msg_lspid, msg_ctime będzie odpowiadać aktualnemu czasowi; msg_qbytes msg_lrpid, msg_stime i msg_rtime inicjowane są zerami (0); msg_qbytes przyjmuje wartość równą ograniczeniu systemowemu MSGMNB (zdefiniowanej w linux/msg.h) jako #define MSGMNB 16384 /* <=INT_MAX,default max size of a message queue*/ Kryspin Mirota, kmirota@ath.bielsko.pl 5

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Zauważmy, że dzięki przyjętemu sposobowi inicjowania pola msg_perm.mode za pośrednictwem argumentu flag, wykorzystując operator alternatywy bitowej ' ' możemy określić w inny sposób niż domniemany uprawnienia flag = IPC_CREAT mode jest to możliwe dzięki temu, że wg definicji stałej IPC_CREAT jej wartość wynosi 512, czyli binarnie 1 000 000 000 a więc właśnie 9 najmłodszych bitów jest nie wykorzystywanych. Uprawnienia są określane, jak i w pozostałych przypadkach, za pomocą maski bitowej read by user (u+r) 00400 0x100 256 write by user (u+w) 00200 0x80 128 read by group (g+r) 00040 0x20 32 write by group (g+w) 00020 0x10 16 read by others (o+r) 00004 0x4 4 write by others (o+r) 00002 0x2 2 Kryspin Mirota, kmirota@ath.bielsko.pl 6

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Chociaż klucz key wywołaniu msgget() może być zadany w sposób dowolny, to jednak w przypadku kiedy będzie wykorzystywany już wcześniej, to funkcja zwróci błąd. W przypadku kiedy: ma być to kolejka prywatna albo użytkowana przez potomków utworzonych funkcją fork() (albo fork() i dalej exec*()) w zupełności wystarczającym jest podstawienie IPC_PRIVATE; jeżeli jednak ma kolejka ma być użytkowana przez procesy niespokrewnione, to wygodnie jest wygenerować wspólny dla wszystkich klucz wywołaniem funkcji ftok(). SYNOPSIS # include <sys/types.h> # include <sys/ipc.h> key_t ftok( const char *pathname,int id ); const char *pathname pewna arbitralnie ustalona ścieżka int id pewien arbitralnie ustalony identyfikator (liczba całkowita niezerowa) RETURN key_t wygenerowany klucz, w przypadku powodzenia ERRORS -1 Jako tako jej zastosowanie nie ogranicza się wyłącznie do identyfikacji kolejek. Kryspin Mirota, kmirota@ath.bielsko.pl 7

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Ogół działań związanych z zarządzaniem kolejką, do której proces posiada uprawnienia, realizuje funkcja msgctl(). SYNOPSIS #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl( int msqid,int cmd, struct msqid_ds *buf ); int msqid identyfikator kolejki komunikatów w tablicy systemowej int cmd rodzaj operacji do wykonanie struct msqid_ds *buf wskazanie do struktury w której będzie zwracany wynik albo z której będą pobierane wartości RETURN 0 w przypadku sukcesu ERRORS -1 Na kolejce mogą być wykonane następujące operacje cmd: IPC_STAT pobranie informacji z systemowej msqid_ds; IPC_SET przekopiowanie wartości zadanych trzecim parametrem formalnym do systemowej struktury msqid_ds; IPC_RMID natychmiastowe usunięcie kolejki komunikatów. Kryspin Mirota, kmirota@ath.bielsko.pl 8

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. W implementacji LINUX'owej uzyskujemy tu nieco większą funkcjonalność w relacji do UNIX SysV czy POSIX. W szczególności określając cmd = IPC_INFO uzyskujemy ogólne informacje odnośnie realizacji i ograniczeń kolejek komunikatów w danym systemie. Wynik zwracany jest w strukturze msginfo (definicja sys/msg.h). struct msginfo { int msgpool; /* --- aktualnie nieużywana --- */ int msgmap; /* --- aktualnie nieużywana --- */ int msgmax; /* max ilość bajtów jaka może być przesłana w pojedynczej wiadomości */ int msgmnb; /* max ale ogółem do kolejki */ int msgmni; /* max ilość kolejek */ int msgssz; /* --- aktualnie nieużywana --- */ int msgtql; /* --- aktualnie nieużywana --- */ }; unsigned short int msgseg; /* --- aktualnie nieużywana --- */ Kryspin Mirota, kmirota@ath.bielsko.pl 9

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Jako przykład przygotujemy program, który utworzy klejkę, pobierze podstawowe informacje na jej temat. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/msg.h> #include <time.h> #define PROJECTID 666 int main( void ) { key_t key; int flag, msqid; struct msqid_ds buffer; Generujemy klucz dla potrzeb utworzenia kolejki podając pewien arbitralnie obrany (ale koniecznie istniejący katalog; z pewnością /tmp będzie istniał), a ponadto pewną wartość liczbową (tutaj stała PROJECTID) key = ftok( "/tmp",_project_id ); Następnie tworzymy kolejkę (uprawnienia odczytu i zapisu tylko dla użytkownika) flag = IPC_CREAT 0x100 0x80; msqid = msgget( key,flag ); Kryspin Mirota, kmirota@ath.bielsko.pl 10

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Sprawdzamy czy faktycznie kolejka powstała, } czyli zostało umieszczone do niej wskazanie w tablicy systemowej if( msqid<0 ){ perror( "!.!..msgget().." ); exit( 1 ); } else { Jeżeli tak, to pobieramy o niej informacje if(!msgctl( msqid,ipc_stat,&buffer ) ) { Identyfikator kolejki printf( "\tkolejka [%d]\n",(int)msqid ); Dla pewności pobieramy nasz UID i GID printf( "\tuid:%d gid:%d\n",(int)getuid(),(int)getgid() );... i sprawdzenia zawartości struct msqid_ds printf( "\t%s",ctime( &(buffer.msg_ctime ) ) ); printf( "\tuid:%dgid:%d\n",(int)buffer.msg_perm.uid, (int)buffer.msg_perm.gid ); printf( "\tkey: 0x%x\n",buffer.msg_perm. key ); printf( "\trozmiar kolejki: %lu B / %u MSG\n", buffer.msg_cbytes,(unsigned)buffer.msg_qnum ); /* msgctl( msqid,ipc_rmid,&buffer ); */ }else{ perror( "!.!..msgctl.." ); exit( 2 ); } } return 0; Kryspin Mirota, kmirota@ath.bielsko.pl 11

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Jeżeli program zapiszemy pod nazwą msgtest.c, to jego kompilacja i konsolidacja $ gcc -Wall msgtest.c -o msgtest Sprawdźmy jeszcze przed uruchomieniem programu listę kolejek w pamięci jądra # ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages czyli brak kolejek. Uruchommy teraz program $./msgtest KOLEJKA [32768] uid:1000 gid:100 Wed Oct 21 09:42:40 2008 uid:1000 gid:100 key: 0x9a060481 rozmiar kolejki: 0 B / 0 MSG Mamy zatem kolejkę : identyfikowaną przez msqid=32768 klucz key=0x9a060481 utworzona msg_ctime=wed Oct 21 09:42:40 2008 właściciela opisuje uid:1000 gid:100, czyli user=kmirota group=users w kolejce jest aktualnie 0 wiadomości. 12 Kryspin Mirota, kmirota@ath.bielsko.pl 12

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Sprawdźmy raz jeszcze już po zakończeniu procesu listę istniejących kolejek $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x9a060481 32768 kmirota 600 0 0 czyli, mimo że proces już nie istnieje kolejka pozostała w pamięci. Co nie mniej istotne, nawet gdyby zamknąć sesję terminala i ponownie otworzyć, to $ ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x9a060481 32768 kmirota 600 0 0 a więc kolejki nie są usuwane automatycznie z pamięci, a wymagają aby wykonał to jawnie proces który kolejką utworzył. Warto pamiętać o tym fakcie, a z naszego kodu należy zmodyfikować wprowadzając zamiast... /* msgctl( msqid,ipc_rmid,&buffer ); */ }else{ perror( "!.!..msgctl.." ); exit( 2 ); } powinno być... msgctl( msqid,ipc_rmid,&buffer ); }else{ perror( "!.!..msgctl.." ); exit( 2 ); } czyli usunąć komentarz. Dopiero teraz kolejka zostanie usunięta z pamięci jądra. 13 Kryspin Mirota, kmirota@ath.bielsko.pl 13

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Przesyłanie do i pobierane z kolejki wywołaniami funkcji msgsnd() i msgrcv(). SYNOPSIS #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd( int msqid,const void *msgp,size_t msgsz,int msgflg ); ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long mtype,int msgflg); int msqid identyfikator kolejki do której wysyłana jest wiadomość void *msgp wskazanie do struktury definiowanej przez wywołującego ( ) struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[msgsz]; /* message data */ }; opisującej typ wiadomości i samą wiadomość size_t msgsz rozmiar łańcucha mtext w strukturze msgp (nie więcej niż MSGMAX=8192, zdefinowane w linux/msg.h) int msgflg jeżeli IPC_NOWAIT to nie czeka na możliwość zapisu lub odczytu long mtype liczna identyfikujące rodzaj komunikatu na liście, służąca ich filtrowaniu RETURN 0 sukces msgsnd(), a msgrcv() ilość bajtów skopiowanych do tablicy mtext ERRORS -1 Kryspin Mirota, kmirota@ath.bielsko.pl 14

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. W wyniku pomyślnego wykonania operacji msgsnd(): msg_lspid będzie ustawione na ID procesu, który wysłał msg_qnum będzie zwiększone o 1 msg_stime uzyska wartość bieżącej chwili czasu natomiast msgrcv(): zapisanie kopi komunikatu wskazywanego przez msgp do kolejki o identyfikatorze msqid oraz jego usunięcie z kolejki systemowej parameter msgsz określa tutaj maksymalna długość łańcucha komunikatu, jeżeli w rzeczywistości długość okaże się większa, to wynik zależy od czego czy w msgflg podano MSG_NOERROR (tak łańcuch będzie obcięty, nie będzie powstanie błąd, czyli zwróci -1) Parametr określający typ wiadomość mtype, który umożliwiający ich filtrowanie na etapie odczytu. Jego użycie w msgrcv() jest następujące: mtype == 0, 0 czytana jest pierwsza dostępna wiadomość w kolejce mtype > 0, 0 pierwsza wiadomość w kolejce o identycznej wartości typu (podany w momencie wysyłania jako parametr msgsnd()), jeżeli jednak MSG_EXCEPT podano w msgflg to odczytana będzie pierwsza i typie różnym od podanego w mtype; mtype < 0, 0 pierwsza wiadomość o typie, w wywołaniu msgsnd(), <= mtype. 15 Kryspin Mirota, kmirota@ath.bielsko.pl 15

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. W kolejnym przykładzie proces utworzy prywatną kolejką, wyśle do niej dwa komunikaty a następnie spróbuje go odebrać. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/msg.h> #define MSGMAX 8192 #define PROJECTID 0x1A int main( void ) { key_t key; unsigned msqid,pid; Definiujemy struktury do obsługi kolejki i przesyłania komunikatów struct msqid_ds buffer; struct { long type; char text[msgmax]; } message; I w końcu inicjujemy kolejkę komunikatów generując klucz przez ftok() key = ftok( "/tmp",projectid ); msqid = msgget( key,ipc_creat 0x100 0x80 ); 16 Kryspin Mirota, kmirota@ath.bielsko.pl 16

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. Jeżeli kolejka msqid zainicjowana pomyślnie, to wysyłamy do niej komunikaty if( msqid<0 ){ perror( "!.!..msgget().." ); exit( 1 ); } else { Niech komunikaty będą identyfikowanej przez PID procesu wysyłającego pid = getpid(); printf( "[%u] utworzył kolejkę...%u\n",pid,msqid ); message.type = (long)pid; Przygotowujemy i wysyłamy pierwszą wiadomość (void) strcpy( message.text, "\'<1> pierwsza wiasomość <1>\'"); printf( "[%u] wysyła...\t%s\n",pid,message.text ); Konstrukcja strlen(message.text)+1 konieczna, ponieważ msgsnd() wymaga potania ilości bajtów, a strlen() zwraca długość łańcucha bez końcowego '\0' msgsnd( msqid,(void*)&message,strlen(message.text)+1,ipc_nowait );... no i druga wiadomość (void) strcpy( message.text, "\'<2> druga wiadomość <2>\'"); printf( "[%u] wysyła...\t%s\n",pid,message.text ); msgsnd( msqid,(void*)&message,strlen(message.text)+1,ipc_nowait ); Teraz zajmiemy się odbiorem wysłanych komunikatów. 17 Kryspin Mirota, kmirota@ath.bielsko.pl 17

z przedmiotu, prowadzonych na Wydziale BMiI, Akademii Techniczno-Humanistycznej w Bielsku-Białej. } } Generalnie lepiej pamiętać o... bzero( (void*)&message,sizeof( message ) ); Dopóki jeszcze coś jest w kolejce identyfikowanego typem pid, to czytamy while( msgrcv( msqid,(void*)&message,msgmax, pid,ipc_nowait MSG_NOERROR ) > 0 ) { printf( "[%u] otrzymał...\t%s\n",pid,message.text ); bzero( (void*)&message,sizeof( message ) ); } Skoro nic nie pozostało, to usuwamy z pamięci naszą kolejkę msgctl( msqid,ipc_rmid,&buffer ); i kończymy return 0; 18 Kryspin Mirota, kmirota@ath.bielsko.pl 18