MSGOP(2) | System Calls Manual | MSGOP(2) |
msgrcv, msgsnd - Opérations sur les files de messages System V
Bibliothèque C standard (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);
Les appels système msgsnd() et msgrcv() servent respectivement à envoyer et à recevoir des messages d'une file de messages System V. Le processus appelant doit avoir une permission d'écriture sur la file pour envoyer un message, et une permission de lecture pour en recevoir un.
L'argument msgp est un pointeur vers une structure définie par l'appelant de la forme générale suivante :
struct msgbuf {
long mtype; /* type de message, doit être > 0 */
char mtext[1]; /* contenu du message */ };
Le champ mtext est un tableau (ou une autre structure) de taille msgsz, valeur entière positive ou nulle. Les messages de taille nulle (sans champ mtext) sont autorisés. Le membre mtype doit avoir une valeur strictement positive qui puisse être utilisée par le processus lecteur pour la sélection de messages (voir la description de msgrcv() ci‐dessous).
L'appel système msgsnd() insère une copie du message pointé par l'argument msgp dans la file dont l'identifiant est indiqué par la valeur de l'argument msqid.
S'il y a assez de place dans la file, msgsnd() réussit immédiatement. La capacité de la file est régie par le champ msg_qbytes de la structure associée à la file de messages. Durant la création de la file, ce champ est initialisé à MSGMNB octets, mais cette limite peut être modifiée avec msgctl(2). Une file de message est considérée pleine si une de ces conditions est remplie :
S'il n'y a pas assez de place, alors le comportement par défaut de msgsnd() est de bloquer jusqu'à obtenir suffisamment d'espace. En indiquant IPC_NOWAIT dans l'argument msgflg, le message ne sera pas envoyé et l'appel système échouera en retournant EAGAIN dans errno.
Un appel à msgsnd() bloqué peut échouer si :
Si l'appel système réussit, la structure décrivant la file de messages est mise à jour comme suit.
L'appel système msgrcv() supprime un message depuis la file indiquée par msqid et le place dans le tampon pointé par msgp.
L'argument msgsz indique la taille maximale en octets du membre mtext de la structure pointée par l'argument msgp. Si le contenu du message est plus long que msgsz octets, le comportement dépend de la présence ou non de MSG_NOERROR dans msgflg. Si MSG_NOERROR est spécifié, alors le message sera tronqué (et la partie tronquée sera perdue) ; si MSG_NOERROR n'est pas spécifié, le message ne sera pas extrait de la file, et l'appel système échouera en renvoyant -1 et en indiquant E2BIG dans errno.
À moins que MSG_COPY ne soit indiqué dans msgflg (voir ci-dessous), l’argument msgtyp indique le type de message désiré.
L'argument msgflg est composé d'un OU binaire « | » avec les attributs suivants.
Si aucun message du type requis n'est disponible et si on n'a pas demandé IPC_NOWAIT dans msgflg, le processus appelant est bloqué jusqu'à l'occurrence d'un des événements suivants:
Si l'appel système réussit, la structure décrivant la file de messages est mise à jour comme suit.
En cas de succès, msgsnd() renvoie 0 et msgrcv() renvoie le nombre d'octets vraiment copiés dans la table mtext. En cas d'échec les deux appels système renvoient -1 et définissent errno pour indiquer l'erreur.
msgsnd() peut échouer avec les valeurs suivantes :
msgrcv() peut échouer avec les valeurs suivantes :
POSIX.1-2001, POSIX.1-2008, SVr4.
Les attributs MSG_EXCEPT et MSG_COPY sont spécifiques à Linux. Leur définition peut être obtenue en définissant la macro de test de fonctionnalités _GNU_SOURCE.
L'argument msgp est déclaré comme un struct msgbuf * avec les bibliothèques glibc 2.0 et glibc 2.1. Il est déclaré comme un void * avec la bibliothèque glibc 2.2, suivant ainsi les spécifications SUSv2 et SUSv3.
Les limites suivantes concernent les files de messages et affectent l’appel msgsnd().
L'implémentation des files de messages sous Linux n'a pas de limites système intrinsèques ni pour le nombre d'en‐têtes de messages (MSGTQL) ni pour la taille, en octets, de l'ensemble de tous les messages (MSGPOOL).
Jusqu'à la version Linux 3.13, si msgrcv() était appelé avec l’attribut MSG_COPY, mais sans IPC_NOWAIT, et que la file de messages contenait moins de msgtyp messages, alors l’appel bloquait jusqu’à ce que le message suivant soit écrit dans la file. À ce moment là, l’appel renvoyait une copie du message, quelle que soit la position ordinale msgtyp de ce message. Ce bogue est corrigé depuis Linux 3.14.
Indiquer à la fois MSG_COPY et MSC_EXCEPT dans msgflg est une erreur de logique (puisque ces attributs imposent des interprétations différentes de msgtyp). Jusqu'à Linux 3.13, cette erreur n’était pas diagnostiquée par msgsrv(). Ce bogue est corrigé depuis Linux 3.14.
Le programme ci-dessous montre l'utilisation de msgsnd() et de msgrcv().
Le programme d'exemple est d'abord exécuté avec l'option -s pour envoyer un message, puis réexécuté avec l'option -r pour recevoir un message.
La session d'interpréteur suivant montre un échantillon d'exécution du programme :
$ ./a.out -s envoi : un message le mercredi 4 mars 2015 à 16:25:45 $ ./a.out -r message reçu : un message le mercredi 4 mars 2015 à 16:25:45
#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, "Utilisation : %s [options]\n", nom_prog);
fprintf(stderr, "Les options sont :\n");
fprintf(stderr, "-s envoyer un message en utilisant msgsnd()\n");
fprintf(stderr, "-r lire un message en utilisant msgrcv()\n");
fprintf(stderr, "-t type de message (1 par défaut)\n");
fprintf(stderr, "-k clé de la file de messages (1234 par défaut)\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), "un message à %s",
ctime(&t));
if (msgsnd(qid, &msg, sizeof(msg.mtext),
IPC_NOWAIT) == -1)
{
perror("msgsnd error");
exit(EXIT_FAILURE);
}
printf("envoyé : %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("Aucun message disponible pour msgrcv()\n");
} else
printf("message reçu : %s\n", msg.mtext);
} } int main(int argc, char *argv[]) {
int qid, opt;
int mode = 0; /* 1 = envoyé, 2 = reçu */
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], "l'option -t doit être plus grande que 0\n");
break;
case 'k':
msgkey = atoi(optarg);
break;
default:
usage(argv[0], "option non reconnue\n");
}
}
if (mode == 0)
usage(argv[0], "doit être l'option -s ou -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)
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.
5 février 2023 | Pages du manuel de Linux 6.03 |