oracular (2) msgrcv.2.gz

Provided by: manpages-pl-dev_4.23.1-1_all bug

NAZWA

       msgrcv, msgsnd - przekazuje komunikaty 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

       Wywołań  systemowych  msgsnd()  i   msgrcv()  używa się do wysyłania komunikatów do kolejki komunikatów i
       odbierania komunikatów z kolejki Systemu V. Aby wysłać komunikat, proces wywołujący musi mieć uprawnienie
       do zapisu na kolejce komunikatów, a aby odebrać komunikat - uprawnienie do odczytu kolejki.

       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 pobiera kopię komunikatu na pozycji porządkowej w kolejce,  określonej  przez  msgtyp
              (komunikaty są rozważane jako numerowane od 0).

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

              Znacznik  MSG_COPY  został  dodany  dla  zaimplementowania w jądrze funkcji przywracania do punktu
              kontrolnego (checkpoint-restore) i jest dostępny 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 przechwyci 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 powodzenia, msgsnd() zwróci 0, a msgrvc() zwróci liczbę  bajtów  skopiowanych  z  kolejki  do
       tablicy mtext. W przypadku błędu, obydwie funkcje zwrócą -1 i ustawią errno, wskazując błąd.

BŁĘDY

       msgsnd() może zawieść z powodu następujących błędów:

       EACCES Proces  wywołujący nie ma prawa do zapisu kolejki komunikatów, ani nie ma przywileju CAP_IPC_OWNER
              (ang. capability) w przestrzeni nazw użytkownika, która zarządza jego przestrzenią nazw IPC.

       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() może zawieść z powodu następujących błędów:

       E2BIG  Tekst komunikatu jest dłuższy niż msgsz i nie ustawiono znacznika MSG_NOERROR w parametrze msgflg.

       EACCES Proces wywołujący nie ma prawa do odczytu kolejki komunikatów, ani nie ma przywileju CAP_IPC_OWNER
              (ang. capability) w przestrzeni nazw użytkownika, która zarządza jego przestrzenią nazw IPC.

       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)
              W   msgflg   określono   MSG_COPY   i   IPC_NOWAIT,  a  jądro  zostało  skonfigurowane  bez  opcji
              CONFIG_CHECKPOINT_RESTORE.

STANDARDY

       POSIX.1-2008.

       Znaczniki MSG_EXCEPT i MSG_COPY są charakterystyczne  dla  Linuksa,  ich  definicje  można  pobrać  przez
       zdefiniowane makra testującego 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 późniejszych
       jest deklarowany jako void *, zgodnie z wymaganiami SUSv2 i SUSv3.

UWAGI

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

USTERKI

       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  i  wcześniejszych,  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
           wysłano: a message at Wed Mar  4 16:25:45 2015

       $ ./a.out -r
       komunikat otrzymano: 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, "Użycie: %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), "wiadomość o %s",
                    ctime(&t));

           if (msgsnd(qid, &msg, sizeof(msg.mtext),
                      IPC_NOWAIT) == -1)
           {
               perror("błąd msgsnd");
               exit(EXIT_FAILURE);
           }
           printf("wysłano: %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("Brak komunikatu dostępnego dla msgrcv()\n");
           } else {
               printf("komunikat otrzymano: %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)

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