Provided by: manpages-pl-dev_4.13-4_all bug

NAZWA

       msgrcv, msgsnd - przekazywanie komunikatów kolejki Systemu V

SKŁADNIA

       #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 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 wskaźnikiem do zdefiniowanej przez proces wywołujący struktury, której
       ogólna postać wygląda tak:

           struct msgbuf {
               long mtype;       /* typ wiadomości, musi być > 0 */
               char mtext[1];    /* dane wiadomości */
           };

       Pole mtext jest tablicą (lub inna strukturą) o rozmiarze określonym przez  msgsz,  będącym
       nieujemną   liczbą   całkowitą.   Dozwolone   są   komunikaty  o  zerowej  długości  (tzn.
       niezawierające pola mtext). Wartość pola mtype musi być liczbą ściśle dodatnią, która może
       służyć  procesowi  odbierającemu  komunikaty  do filtrowania kolejki (zobacz opis msgrcv()
       poniżej).

   msgsnd()
       Wywołanie systemowe msgsnd() dołącza kopię komunikatu wskazywanego przez msgp do kolejki o
       identyfikatorze określonym przez msqid.

       Gdy  w  kolejce  jest  wystarczająco  dużo  miejsca,  to  msgsnd()  natychmiast kończy się
       pomyślnie.  (Pojemność  kolejki  określona  jest  w  polu  msg_qbytes   struktury   danych
       stowarzyszonej  z  kolejką.  Podczas tworzenia kolejki polu temu jest przypisywana wartość
       początkowa wynosząca MSGMNB bajtów, lecz ograniczenie to może zostać zmienione  za  pomocą
       msgctl(2)). Kolejka komunikatów jest uważana za pełną w jednym z następujących przypadków:

       • Dodanie  nowego  komunikatu  do  kolejki  spowoduje, że suma bajtów w kolejki przekroczy
         maksymalny rozmiar kolejki (pole msg_qbytes).

       • Dodanie kolejnego komunikatu do kolejki spowoduje, że  całkowita  liczba  komunikatów  w
         kolejce  przekroczy  maksymalny  rozmiar  kolejki (pole msg_qbytes). To sprawdzenie jest
         konieczne aby zapobiec umieszczaniu  w  kolejce  nieograniczonej  liczby  komunikatów  o
         zerowej  długości.  Choć  takie  komunikaty  nie  zawierają  danych,  to  wciąż  zajmują
         (zablokowaną) pamięć jądra.

       Jeśli  w  kolejce  obecna  jest  niewystarczająca  ilość  wolnego  miejsca,  to   domyślne
       zachowaniem  msgsnd() jest blokada do momentu uzyskania wolnej przestrzeni. Jeśli w msgflg
       określono IPC_NOWAIT, to zamiast tego wywołanie zwróci błąd EAGAIN.

       Wstrzymane wywołanie msgsnd() może się także nie powieść, jeżeli:

       • kolejka zostanie usunięta z systemu - w tym przypadku wywołanie systemowe  zgłosi  błąd,
         przypisując zmiennej errno wartość EIDRM;

       • zostanie  przechwycony  sygnał  - wtedy wywołanie to powoduje przypisanie zmiennej errno
         wartości EINTR; patrz signal(7) (msgsnd() po przerwaniu przez obsługę sygnału  nie  jest
         nigdy   automatycznie  restartowane,  niezależnie  od  ustawienia  znacznika  SA_RESTART
         podanego podczas ustanawiania funkcji obsługi sygnału).

       Jeśli operacja zakończy się pomyślnie, to  struktura  danych  opisująca  kolejkę  zostanie
       zmodyfikowana w następujący sposób:

       • msg_lspid przypisany zostanie identyfikator procesu wykonującego tę operację.

       • msg_qnum zostanie zwiększone o 1.

       • msg_stime zostanie przypisany bieżący czas.

   msgrcv()
       Wywołanie systemowe msgrcv usuwa komunikat z kolejki określonej przez msqid i umieszcza go
       w buforze wskazywanym przez parametr msgp.

       Parametr msgsz określa maksymalny rozmiar w bajtach pola mtext struktury wskazywanej przez
       parametr  msgp.  Jeśli dane komunikatu zajmują więcej bajtów niż msgsz, to wynik zależy od
       tego, czy w msgflg przekazano znacznik MSG_NOERROR. Jeżeli podano  MSG_NOERROR,  to  tekst
       komunikatu  zostanie  obcięty  (obcięta  część  zostanie utracona); jeżeli MSG_NOERROR nie
       występuje, to komunikat nie jest usuwany z  kolejki,  a  wywołanie  systemowe  kończy  się
       błędem, zwracając wartość -1 i ustawiając errno na E2BIG.

       Jeżeli  podano MSG_COPY w msgflg (zob. poniżej), parametr msgtyp określa rodzaj komunikatu
       w następujący sposób:

       • Jeśli msgtyp jest równy 0, to czytany jest pierwszy komunikat z kolejki.

       • Jeśli msgtyp ma wartość większą niż 0, to z kolejki odczytywany jest pierwszy  komunikat
         o  typie msgtyp, chyba że w parametrze msgflg zostanie ustawiony znacznik MSG_EXCEPT, co
         spowoduje, że z kolejki zostanie odczytany pierwszy komunikat o typie różnym od msgtyp.

       • Jeśli msgtyp ma wartość mniejszą  niż  0,  to  z  kolejki  zostanie  odczytany  pierwszy
         komunikat o najniższym numerze typu, mniejszym lub równym wartości bezwzględnej msgtyp.

       Parametr  msgflg  jest  maską  bitową,  utworzoną  jako  alternatywa  (OR) zera lub więcej
       następujących znaczników:

       IPC_NOWAIT
              Nie wstrzymuje pracy procesu, jeśli w  kolejce  nie  ma  komunikatów  odpowiedniego
              typu.  Wywołanie  systemowe zwróci wówczas błąd, przypisując zmiennej errno wartość
              ENOMSG.

       MSG_COPY (od Linuksa 3.8)
              Nieniszcząco pobiega kopię komunikatu w  pozycję  porządkową  w  kolejce  określoną
              przez msgtyp (komunikaty są pomyślane do numerowania od 0).

              Tę  flagę należy podać w połączeniu z IPC_NOWAIT, co skutkuje tym, że jeśli w danej
              pozycji nie ma dostępnego komunikatu, to wywołanie natychmiast zwraca błąd  ENOMSG.
              Ponieważ  zmienia  to  znaczenie  msgtyp  w różny sposób, MSG_COPY i MSG_EXCEPT nie
              mogą być podane równocześnie w msgflg.

              Flaga MSG_COPY została dodana dla zaimplementowania w jądrze  funkcji  przywracania
              do  punktu  kontrolnego (checkpoint-restore) i jest dostępna wyłącznie wtedy, jeśli
              jądro zbudowano z opcją CONFIG_CHECKPOINT_RESTORE.

       MSG_EXCEPT
              Użyte z parametrem msgtyp większym od 0, spowoduje odczytanie z kolejki  pierwszego
              komunikatu o typie różnym od msgtyp.

       MSG_NOERROR
              Spowoduje obcięcie komunikatu, jeśli jego dane są dłuższe niż msgsz bajtów.

       Jeśli  w  kolejce  nie  ma  komunikatu spełniającego te warunki, a znacznik IPC_NOWAIT nie
       został ustawiony w msgflg, to proces zostanie  wstrzymany,  dopóki  nie  nastąpi  jedno  z
       poniższych zdarzeń:

       • Komunikat odpowiedniego typu zostanie umieszczony w kolejce.

       • Kolejka  zostanie  usunięta  z systemu. W tym przypadku wywołanie systemowe zgłosi błąd,
         przypisując zmiennej errno wartość EIDRM.

       • Proces wywołujący przechwytuje sygnał. W takim przypadku wywołanie systemowe kończy  się
         niepowodzeniem, ustawiając errno na EINTR. (msgrcv() po przerwaniu przez obsługę sygnału
         nie  jest  nigdy  automatycznie  restartowane,  niezależnie  od   ustawienia   znacznika
         SA_RESTART podczas ustanawiania funkcji obsługi sygnału).

       Jeśli  operacja  zakończy  się  pomyślnie,  to struktura danych opisująca kolejkę zostanie
       zmodyfikowana w następujący sposób:

              msg_lrpid przyjmie wartość równą identyfikatorowi wołającego procesu

              msg_qnum zostanie zmniejszone o 1.

              msg_rtime zostanie przypisany bieżący czas.

WARTOŚĆ ZWRACANA

       W przypadku niepowodzenia obydwa wywołania zwrócą -1 i przypiszą  zmiennej  errno  wartość
       określającą  rodzaj  błędu.  W  przeciwnym przypadku, msgsnd() zwróci 0, a msgrvc() zwróci
       liczbę bajtów skopiowanych z kolejki do tablicy mtext.

BŁĘDY

       Jeśli wywołanie msgsnd() się nie powiedzie, to zmienna errno przyjmie jedną  z  poniższych
       wartości:

       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  może  zostać  wysłany  z powodu ograniczenia msg_qbytes dotyczącego
              kolejki, a nie przekazano znacznika IPC_NOWAIT w parametrze mgsflg.

       EFAULT Adres wskazywany przez msgp jest niedostępny.

       EIDRM  Kolejka komunikatów została usunięta.

       EINTR  Podczas oczekiwania na zwolnienie miejsca w kolejce, proces przechwycił sygnał.

       EINVAL Niewłaściwa wartość msqid, mtype (powinna być  dodatnia)  lub  msgsz  (powinna  być
              większa lub równa 0 i mniejsza lub równa MSGMAX).

       ENOMEM Brak w systemie pamięci na skopiowanie komunikatu wskazywanego przez msgp.

       Jeśli  wywołanie msgrcv() się nie powiedzie, to zmiennej errno zostanie przypisana jedna z
       poniższych wartości:

       E2BIG  Tekst komunikatu jest dłuższy niż 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 niedostępny.

       EIDRM  Proces oczekiwał na komunikat, ale w międzyczasie kolejka została usunięta.

       EINTR  Proces  przechwycił  sygnał  podczas  oczekiwania  na  odebranie  komunikatu; patrz
              signal(7).

       EINVAL msqid był niepoprawny lub msgsz był mniejszy od 0.

       EINVAL (od Linuksa 3.14)
              msgflg określono jako MSG_COPY, ale nie IPC_NOWAIT.

       EINVAL (od Linuksa 3.14)
              msgflg określono jako MSG_COPY i MSG_EXCEPT.

       ENOMSG Znacznik IPC_NOWAIT został przekazany w msgflg, ale w  kolejce  nie  ma  komunikatu
              żądanego typu.

       ENOMSG IPC_NOWAIT  i  MSG_COPY  zostały  określone  w  msgflg, a kolejka zawiera mniej niż
              msgtyp komunikatów.

       ENOSYS (od Linuksa 3.8)
              Both MSG_COPY and  IPC_NOWAIT  were  specified  in  msgflg,  and  this  kernel  was
              configured without CONFIG_CHECKPOINT_RESTORE.

ZGODNE Z

       POSIX.1-2001, POSIX.1-2008, SVr4.

       Znaczniki  MSG_EXCEPT  i  MSG_COPY  są  charakterystyczne dla Linuksa, ich definicje można
       pobrać przez zdefiniowane makra testującego funkcje _GNU_SOURCE.

UWAGI

       Dołączenie <sys/types.h> i <sys/ipc.h> nie jest wymagane na Linuksie  ani  przez  żadną  z
       wersji  POSIX.  Jednak  niektóre  stare  implementacje  wymagają  dołączenia  tych  plików
       nagłówkowych, SVID również dokumentuje ich dołączenie. Aplikacje które mają być  przenośne
       na tego typu stare systemy mogą wymagać dołączenia omawianych plików nagłówkowych.

       Parametr msgp jest deklarowany jako struct msgbuf * w glibc 2.0 i glibc 2.1. W glibc 2.2 i
       późniejszych jest deklarowany jako void *, zgodnie z wymaganiami SUSv2 i SUSv3.

       Wywołania msgsnd() dotyczą następujące ograniczenia systemowe:

       MSGMAX Maksymalny rozmiar tekstu komunikatu, w bajtach: (domyślna  wartość:  8192  bajty).
              Pod   Linuksem   ten   limit   można   odczytać   i   modyfikować,  używając  pliku
              /proc/sys/kernel/msgmax.

       MSGMNB Maksymalna  liczba  bajtów  która  może  być przechowywana  w  kolejce  komunikatów
              (domyślna  wartość: 16384 bajtów). Pod Linuksem można ten limit odczytać i zmienić,
              używając pliku /proc/sys/kernel/msgmnb. Proces uprzywilejowany (w Linuksie:  proces
              z  przywilejem  CAP_SYS_RESOURCE)  może  zwiększyć rozmiar kolejki komunikatów poza
              MSGMNB za pomocą operacji IPC_SET msgctl(2).

       W  tej  implementacji  nie  ma  jawnego  systemowego   ograniczenia   liczby   komunikatów
       przechowywanych  w  kolejce  (MSGTQL)  i  na rozmiar obszaru (w bajtach) przeznaczonego na
       komunikaty (MSGPOOL).

BŁĘDY

       W Linuksie 3.13 i wcześniejszych, jeśli msgrcv() było wywołane  ze  znacznikiem  MSG_COPY,
       lecz  bez  IPC_NOWAIT,  a  kolejka  komunikatów zawierała mniej niż msgtyp komunikatów, to
       wywołanie było zablokowane aż do zapisania kolejnego komunikatu do kolejki. W tym momencie
       wywołanie  zwracało kopię komunikatu bez względu na to czy komunikat był w pozycji msgtyp.
       Błąd ten został naprawiony w jądrze Linux 3.14.

       Podanie zarówno w msgflg zarówno MSG_COPY jak i MSC_EXCEPT jest błędem logicznym (ponieważ
       oba  te  znaczniki  wymagają innej interpretacji msgtyp). W Linuksie 3.13 błąd ten nie był
       diagnozowany przez msgsrv(). Zostało to naprawione w jądrze Linux 3.14.

PRZYKŁADY

       Program poniżej demonstruje użycie msgsnd() i msgrcv().

       Przykładowy program jest początkowo uruchomiony  z  opcją  -s,  aby  wysłać  komunikat,  a
       następnie ponownie z opcją -r, aby otrzymać komunikat.

       Poniższa sesja powłoki pokazuje przykładowy 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 źródłowy programu

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <time.h>
       #include <unistd.h>
       #include <errno.h>
       #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>

       struct msgbuf {
           long mtype;
           char mtext[80];
       };

       static void
       usage(char *prog_name, char *msg)
       {
           if (msg != NULL)
               fputs(msg, stderr);

           fprintf(stderr, "Uzycie: %s [opcje]\n", nazwa_prog);
           fprintf(stderr, "Opcje:\n");
           fprintf(stderr, "-s        wysyła komunikat przez msgsnd()\n");
           fprintf(stderr, "-r        odczytuje komunikat przez msgrcv()\n");
           fprintf(stderr, "-t        typ komunikatu (domyślnie: 1)\n");
           fprintf(stderr, "-k        klucz kolejki komunikatu (domyślnie: 1234)\n");
           exit(EXIT_FAILURE);
       }

       static void
       send_msg(int qid, int msgtype)
       {
           struct msgbuf msg;
           time_t t;

           msg.mtype = msgtype;

           time(&t);
           snprintf(msg.mtext, sizeof(msg.mtext), "wiadomość o %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 = wysłanie, 2 = otrzymanie */
           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], "opcja -t musi być większa od 0\n");
                   break;
               case 'k':
                   msgkey = atoi(optarg);
                   break;
               default:
                   usage(argv[0], "Nierozpoznana opcja\n");
               }
           }

           if (mode == 0)
               usage(argv[0], "musi być opcją -s albo -r\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 TAKŻE

       msgctl(2), msgget(2), capabilities(7), mq_overview(7), sysvipc(7)

O STRONIE

       Angielska  wersja  tej  strony  pochodzi  z  wydania  5.10  projektu Linux man-pages. Opis
       projektu, informacje dotyczące zgłaszania błędów oraz  najnowszą  wersję  oryginału  można
       znaleźć pod adresem https://www.kernel.org/doc/man-pages/.

T◈UMACZENIE

       Autorami   polskiego   tłumaczenia   niniejszej   strony  podręcznika  są:  Rafał  Lewczuk
       <R.Lewczuk@elka.pw.edu.p>,  Andrzej  Krzysztofowicz   <ankry@green.mf.pg.gda.pl>,   Robert
       Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

       Niniejsze  tłumaczenie  jest  wolną  dokumentacją. Bliższe informacje o warunkach licencji
       można   uzyskać   zapoznając   się   z   GNU   General   Public   License   w   wersji   3
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   lub   nowszej.   Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

       Błędy w tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej
       ⟨manpages-pl-list@lists.sourceforge.net⟩.