Provided by: manpages-pl-dev_0.7-2_all 

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.
Linux 2015-08-08 MSGOP(2)