Provided by: manpages-pl-dev_4.21.0-2_all bug

NAZWA

       msgrcv, msgsnd - przekazywanie komunikatów kolejki Systemu V

BIBLIOTEKA

       Standardowa biblioteka C (libc, -lc)

SKŁADNIA

       #include <sys/msg.h>

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

       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.

BŁĘDY

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

       msgrcv()  can fail with the following errors:

       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.

STANDARDY

       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

       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 <errno.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/ipc.h>
       #include <sys/msg.h>
       #include <time.h>
       #include <unistd.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)
       {
           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], "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)

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

Linux man-pages 6.03                            5 lutego 2023 r.                                        MSGOP(2)