| MSGOP(2) | System Calls Manual | MSGOP(2) |
msgrcv, msgsnd - przekazuje komunikaty kolejki Systemu V
Standardowa biblioteka C (libc, -lc)
#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);
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).
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:
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:
Jeśli operacja zakończy się pomyślnie, to struktura danych opisująca kolejkę zostanie zmodyfikowana w następujący sposób:
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:
Parametr msgflg jest maską bitową, utworzoną jako alternatywa (OR) zera lub więcej następujących znacznikó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ń:
Jeśli operacja zakończy się pomyślnie, to struktura danych opisująca kolejkę zostanie zmodyfikowana w następujący sposób:
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.
msgsnd() może zawieść z powodu następujących błędów:
msgrcv() może zawieść z powodu następujących błędów:
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.
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.
Wywołania msgsnd() dotyczą następujące ograniczenia systemowe:
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).
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.
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
#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);
}
msgctl(2), msgget(2), capabilities(7), mq_overview(7), sysvipc(7)
Tłumaczenie niniejszej strony podręcznika: 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.
| 15 czerwca 2024 r. | Linux man-pages 6.9.1 |