MSGOP(2) | System Calls Manual | MSGOP(2) |
msgrcv, msgsnd - przekazywanie komunikatów 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);
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).
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:
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.
msgsnd() can fail with the following errors:
msgrcv() can fail with the following errors:
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.
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 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 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
#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); }
msgctl(2), msgget(2), capabilities(7), mq_overview(7), sysvipc(7)
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.
5 lutego 2023 r. | Linux man-pages 6.03 |