focal (2) msgsnd.2.gz

Provided by: manpages-pl-dev_0.7-2_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

       Wywołań  systemowych  msgsnd()  i  msgrcv() używa się do - odpowiednio - 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  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 Proces  wywołujący  nie  ma  prawa  do  zapisu  danej  kolejki komunikatów, ani nie ma ustawionego
              atrybutu  CAP_IPC_OWNER.

       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 Proces  wywołujący  nie  ma  prawa  do  odczytu  danej kolejki komunikatów, ani nie ma ustawionego
              atrybutu CAP_IPC_OWNER.

       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)
              MSG_COPY   zostało   określone   w   msgflg,   a   jądro   zostało   skonfigurowane   bez    opcji
              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ŁAD

       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

   Źródło 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, (void *) &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, (void *) &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), svipc(7)

O STRONIE

       Angielska wersja tej strony pochodzi z wydania 4.07 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   man   są:   Rafał   Lewczuk   (PTM)
       <R.Lewczuk@elka.pw.edu.p>,   Andrzej   Krzysztofowicz   (PTM)   <ankry@mif.pg.gda.pl>,   Robert   Luberda
       <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.

       Polskie tłumaczenie jest częścią  projektu  manpages-pl;  uwagi,  pomoc,  zgłaszanie  błędów  na  stronie
       http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją  4.07 oryginału.