MSGOP(2) System Calls Manual MSGOP(2) NAZWA msgrcv, msgsnd - przekazywanie komunikatow kolejki Systemu V BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include int msgsnd(int msqid, const void msgp[.msgsz], size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void msgp[.msgsz], size_t msgsz, long msgtyp, int msgflg); OPIS The msgsnd() and msgrcv() system calls are used to send messages to, and receive messages from, a System V message queue. The calling process must have write permission on the message queue in order to send a message, and read permission to receive a message. Parametr msgp jest wskaznikiem do zdefiniowanej przez proces wywolujacy struktury, ktorej ogolna postac wyglada tak: struct msgbuf { long mtype; /* typ wiadomosci, musi byc > 0 */ char mtext[1]; /* dane wiadomosci */ }; Pole mtext jest tablica (lub inna struktura) o rozmiarze okreslonym przez msgsz, bedacym nieujemna liczba calkowita. Dozwolone sa komunikaty o zerowej dlugosci (tzn. niezawierajace pola mtext). Wartosc pola mtype musi byc liczba scisle dodatnia, ktora moze sluzyc procesowi odbierajacemu komunikaty do filtrowania kolejki (zobacz opis msgrcv() ponizej). msgsnd() Wywolanie systemowe msgsnd() dolacza kopie komunikatu wskazywanego przez msgp do kolejki o identyfikatorze okreslonym przez msqid. Gdy w kolejce jest wystarczajaco duzo miejsca, to msgsnd() natychmiast konczy sie pomyslnie. (Pojemnosc kolejki okreslona jest w polu msg_qbytes struktury danych stowarzyszonej z kolejka. Podczas tworzenia kolejki polu temu jest przypisywana wartosc poczatkowa wynoszaca MSGMNB bajtow, lecz ograniczenie to moze zostac zmienione za pomoca msgctl(2)). Kolejka komunikatow jest uwazana za pelna w jednym z nastepujacych przypadkow: o Dodanie nowego komunikatu do kolejki spowoduje, ze suma bajtow w kolejki przekroczy maksymalny rozmiar kolejki (pole msg_qbytes). o Dodanie kolejnego komunikatu do kolejki spowoduje, ze calkowita liczba komunikatow w kolejce przekroczy maksymalny rozmiar kolejki (pole msg_qbytes). To sprawdzenie jest konieczne aby zapobiec umieszczaniu w kolejce nieograniczonej liczby komunikatow o zerowej dlugosci. Choc takie komunikaty nie zawieraja danych, to wciaz zajmuja (zablokowana) pamiec jadra. Jesli w kolejce obecna jest niewystarczajaca ilosc wolnego miejsca, to domyslne zachowaniem msgsnd() jest blokada do momentu uzyskania wolnej przestrzeni. Jesli w msgflg okreslono IPC_NOWAIT, to zamiast tego wywolanie zwroci blad EAGAIN. Wstrzymane wywolanie msgsnd() moze sie takze nie powiesc, jezeli: o kolejka zostanie usunieta z systemu - w tym przypadku wywolanie systemowe zglosi blad, przypisujac zmiennej errno wartosc EIDRM; o zostanie przechwycony sygnal - wtedy wywolanie to powoduje przypisanie zmiennej errno wartosci EINTR; patrz signal(7) (msgsnd() po przerwaniu przez obsluge sygnalu nie jest nigdy automatycznie restartowane, niezaleznie od ustawienia znacznika SA_RESTART podanego podczas ustanawiania funkcji obslugi sygnalu). Jesli operacja zakonczy sie pomyslnie, to struktura danych opisujaca kolejke zostanie zmodyfikowana w nastepujacy sposob: o msg_lspid przypisany zostanie identyfikator procesu wykonujacego te operacje. o msg_qnum zostanie zwiekszone o 1. o msg_stime zostanie przypisany biezacy czas. msgrcv() Wywolanie systemowe msgrcv usuwa komunikat z kolejki okreslonej przez msqid i umieszcza go w buforze wskazywanym przez parametr msgp. Parametr msgsz okresla maksymalny rozmiar w bajtach pola mtext struktury wskazywanej przez parametr msgp. Jesli dane komunikatu zajmuja wiecej bajtow niz msgsz, to wynik zalezy od tego, czy w msgflg przekazano znacznik MSG_NOERROR. Jezeli podano MSG_NOERROR, to tekst komunikatu zostanie obciety (obcieta czesc zostanie utracona); jezeli MSG_NOERROR nie wystepuje, to komunikat nie jest usuwany z kolejki, a wywolanie systemowe konczy sie bledem, zwracajac wartosc -1 i ustawiajac errno na E2BIG. Jezeli podano MSG_COPY w msgflg (zob. ponizej), parametr msgtyp okresla rodzaj komunikatu w nastepujacy sposob: o Jesli msgtyp jest rowny 0, to czytany jest pierwszy komunikat z kolejki. o Jesli msgtyp ma wartosc wieksza niz 0, to z kolejki odczytywany jest pierwszy komunikat o typie msgtyp, chyba ze w parametrze msgflg zostanie ustawiony znacznik MSG_EXCEPT, co spowoduje, ze z kolejki zostanie odczytany pierwszy komunikat o typie roznym od msgtyp. o Jesli msgtyp ma wartosc mniejsza niz 0, to z kolejki zostanie odczytany pierwszy komunikat o najnizszym numerze typu, mniejszym lub rownym wartosci bezwzglednej msgtyp. Parametr msgflg jest maska bitowa, utworzona jako alternatywa (OR) zera lub wiecej nastepujacych znacznikow: IPC_NOWAIT Nie wstrzymuje pracy procesu, jesli w kolejce nie ma komunikatow odpowiedniego typu. Wywolanie systemowe zwroci wowczas blad, przypisujac zmiennej errno wartosc ENOMSG. MSG_COPY (od Linuksa 3.8) Nieniszczaco pobiega kopie komunikatu w pozycje porzadkowa w kolejce okreslona przez msgtyp (komunikaty sa pomyslane do numerowania od 0). Te flage nalezy podac w polaczeniu z IPC_NOWAIT, co skutkuje tym, ze jesli w danej pozycji nie ma dostepnego komunikatu, to wywolanie natychmiast zwraca blad ENOMSG. Poniewaz zmienia to znaczenie msgtyp w rozny sposob, MSG_COPY i MSG_EXCEPT nie moga byc podane rownoczesnie w msgflg. Flaga MSG_COPY zostala dodana dla zaimplementowania w jadrze funkcji przywracania do punktu kontrolnego (checkpoint-restore) i jest dostepna wylacznie wtedy, jesli jadro zbudowano z opcja CONFIG_CHECKPOINT_RESTORE. MSG_EXCEPT Uzyte z parametrem msgtyp wiekszym od 0, spowoduje odczytanie z kolejki pierwszego komunikatu o typie roznym od msgtyp. MSG_NOERROR Spowoduje obciecie komunikatu, jesli jego dane sa dluzsze niz msgsz bajtow. Jesli w kolejce nie ma komunikatu spelniajacego te warunki, a znacznik IPC_NOWAIT nie zostal ustawiony w msgflg, to proces zostanie wstrzymany, dopoki nie nastapi jedno z ponizszych zdarzen: o Komunikat odpowiedniego typu zostanie umieszczony w kolejce. o Kolejka zostanie usunieta z systemu. W tym przypadku wywolanie systemowe zglosi blad, przypisujac zmiennej errno wartosc EIDRM. o Proces wywolujacy przechwytuje sygnal. W takim przypadku wywolanie systemowe konczy sie niepowodzeniem, ustawiajac errno na EINTR. (msgrcv() po przerwaniu przez obsluge sygnalu nie jest nigdy automatycznie restartowane, niezaleznie od ustawienia znacznika SA_RESTART podczas ustanawiania funkcji obslugi sygnalu). Jesli operacja zakonczy sie pomyslnie, to struktura danych opisujaca kolejke zostanie zmodyfikowana w nastepujacy sposob: msg_lrpid przyjmie wartosc rowna identyfikatorowi wolajacego procesu msg_qnum zostanie zmniejszone o 1. msg_rtime zostanie przypisany biezacy czas. WARTOSC ZWRACANA On success, msgsnd() returns 0 and msgrcv() returns the number of bytes actually copied into the mtext array. On failure, both functions return -1, and set errno to indicate the error. BLEDY msgsnd() can fail with the following errors: EACCES The calling process does not have write permission on the message queue, and does not have the CAP_IPC_OWNER capability in the user namespace that governs its IPC namespace. EAGAIN Komunikat nie moze zostac wyslany z powodu ograniczenia msg_qbytes dotyczacego kolejki, a nie przekazano znacznika IPC_NOWAIT w parametrze mgsflg. EFAULT Adres wskazywany przez msgp jest niedostepny. EIDRM Kolejka komunikatow zostala usunieta. EINTR Podczas oczekiwania na zwolnienie miejsca w kolejce, proces przechwycil sygnal. EINVAL Niewlasciwa wartosc msqid, mtype (powinna byc dodatnia) lub msgsz (powinna byc wieksza lub rowna 0 i mniejsza lub rowna MSGMAX). ENOMEM Brak w systemie pamieci na skopiowanie komunikatu wskazywanego przez msgp. msgrcv() can fail with the following errors: E2BIG Tekst komunikatu jest dluzszy niz msgsz i nie ustawiono znacznika MSG_NOERROR w parametrze msgflg. EACCES The calling process does not have read permission on the message queue, and does not have the CAP_IPC_OWNER capability in the user namespace that governs its IPC namespace. EFAULT Adres wskazywany przez msgp jest niedostepny. EIDRM Proces oczekiwal na komunikat, ale w miedzyczasie kolejka zostala usunieta. EINTR Proces przechwycil sygnal podczas oczekiwania na odebranie komunikatu; patrz signal(7). EINVAL msqid byl niepoprawny lub msgsz byl mniejszy od 0. EINVAL (od Linuksa 3.14) msgflg okreslono jako MSG_COPY, ale nie IPC_NOWAIT. EINVAL (od Linuksa 3.14) msgflg okreslono jako MSG_COPY i MSG_EXCEPT. ENOMSG Znacznik IPC_NOWAIT zostal przekazany w msgflg, ale w kolejce nie ma komunikatu zadanego typu. ENOMSG IPC_NOWAIT i MSG_COPY zostaly okreslone w msgflg, a kolejka zawiera mniej niz msgtyp komunikatow. ENOSYS (od Linuksa 3.8) Both MSG_COPY and IPC_NOWAIT were specified in msgflg, and this kernel was configured without CONFIG_CHECKPOINT_RESTORE. STANDARDY POSIX.1-2008. Znaczniki MSG_EXCEPT i MSG_COPY sa charakterystyczne dla Linuksa, ich definicje mozna pobrac przez zdefiniowane makra testujacego funkcje _GNU_SOURCE. HISTORIA POSIX.1-2001, SVr4. Parametr msgp jest deklarowany jako struct msgbuf * w glibc 2.0 i glibc 2.1. W glibc 2.2 i pozniejszych jest deklarowany jako void *, zgodnie z wymaganiami SUSv2 i SUSv3. UWAGI Wywolania msgsnd() dotycza nastepujace ograniczenia systemowe: MSGMAX Maksymalny rozmiar tekstu komunikatu, w bajtach: (domyslna wartosc: 8192 bajty). Pod Linuksem ten limit mozna odczytac i modyfikowac, uzywajac pliku /proc/sys/kernel/msgmax. MSGMNB Maksymalna liczba bajtow ktora moze byc przechowywana w kolejce komunikatow (domyslna wartosc: 16384 bajtow). Pod Linuksem mozna ten limit odczytac i zmienic, uzywajac pliku /proc/sys/kernel/msgmnb. Proces uprzywilejowany (w Linuksie: proces z przywilejem CAP_SYS_RESOURCE) moze zwiekszyc rozmiar kolejki komunikatow poza MSGMNB za pomoca operacji IPC_SET msgctl(2). W tej implementacji nie ma jawnego systemowego ograniczenia liczby komunikatow przechowywanych w kolejce (MSGTQL) i na rozmiar obszaru (w bajtach) przeznaczonego na komunikaty (MSGPOOL). USTERKI W Linuksie 3.13 i wczesniejszych, jesli msgrcv() bylo wywolane ze znacznikiem MSG_COPY, lecz bez IPC_NOWAIT, a kolejka komunikatow zawierala mniej niz msgtyp komunikatow, to wywolanie bylo zablokowane az do zapisania kolejnego komunikatu do kolejki. W tym momencie wywolanie zwracalo kopie komunikatu bez wzgledu na to czy komunikat byl w pozycji msgtyp. Blad ten zostal naprawiony w jadrze Linux 3.14. Podanie zarowno w msgflg zarowno MSG_COPY jak i MSC_EXCEPT jest bledem logicznym (poniewaz oba te znaczniki wymagaja innej interpretacji msgtyp). W Linuksie 3.13 blad ten nie byl diagnozowany przez msgsrv(). Zostalo to naprawione w jadrze Linux 3.14. PRZYKLADY Program ponizej demonstruje uzycie msgsnd() i msgrcv(). Przykladowy program jest poczatkowo uruchomiony z opcja -s, aby wyslac komunikat, a nastepnie ponownie z opcja -r, aby otrzymac komunikat. Ponizsza sesja powloki pokazuje przykladowy przebieg programu: $ ./a.out -s sent: a message at Wed Mar 4 16:25:45 2015 $ ./a.out -r message received: a message at Wed Mar 4 16:25:45 2015 Kod zrodlowy programu #include #include #include #include #include #include #include struct msgbuf { long mtype; char mtext[80]; }; static void usage(char *prog_name, char *msg) { if (msg != NULL) fputs(msg, stderr); fprintf(stderr, "Usage: %s [options]\n", prog_name); fprintf(stderr, "Options are:\n"); fprintf(stderr, "-s send message using msgsnd()\n"); fprintf(stderr, "-r read message using msgrcv()\n"); fprintf(stderr, "-t message type (default is 1)\n"); fprintf(stderr, "-k message queue key (default is 1234)\n"); exit(EXIT_FAILURE); } static void send_msg(int qid, int msgtype) { time_t t; struct msgbuf msg; msg.mtype = msgtype; time(&t); snprintf(msg.mtext, sizeof(msg.mtext), "a message at %s", ctime(&t)); if (msgsnd(qid, &msg, sizeof(msg.mtext), IPC_NOWAIT) == -1) { perror("msgsnd error"); exit(EXIT_FAILURE); } printf("sent: %s\n", msg.mtext); } static void get_msg(int qid, int msgtype) { struct msgbuf msg; if (msgrcv(qid, &msg, sizeof(msg.mtext), msgtype, MSG_NOERROR | IPC_NOWAIT) == -1) { if (errno != ENOMSG) { perror("msgrcv"); exit(EXIT_FAILURE); } printf("No message available for msgrcv()\n"); } else { printf("message received: %s\n", msg.mtext); } } int main(int argc, char *argv[]) { int qid, opt; int mode = 0; /* 1 = send, 2 = receive */ int msgtype = 1; int msgkey = 1234; while ((opt = getopt(argc, argv, "srt:k:")) != -1) { switch (opt) { case 's': mode = 1; break; case 'r': mode = 2; break; case 't': msgtype = atoi(optarg); if (msgtype <= 0) usage(argv[0], "-t option must be greater than 0\n"); break; case 'k': msgkey = atoi(optarg); break; default: usage(argv[0], "Unrecognized option\n"); } } if (mode == 0) usage(argv[0], "must use either -s or -r option\n"); qid = msgget(msgkey, IPC_CREAT | 0666); if (qid == -1) { perror("msgget"); exit(EXIT_FAILURE); } if (mode == 2) get_msg(qid, msgtype); else send_msg(qid, msgtype); exit(EXIT_SUCCESS); } ZOBACZ TAKZE msgctl(2), msgget(2), capabilities(7), mq_overview(7), sysvipc(7) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Rafal Lewczuk , Andrzej Krzysztofowicz , Robert Luberda i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.06 31 pazdziernika 2023 r. MSGOP(2)