mq_notify - S'enregistrer pour la réception d'une notification de
l'arrivée d'un nouveau message
Bibliothèque de temps réel (
librt,
-lrt)
#include <mqueue.h>
#include <signal.h> /* Définition des constantes SIGEV_* */
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
mq_notify() permet à un processus appelant de s'enregistrer ou de
ne plus s'enregistrer pour délivrer une notification asynchrone
lorsqu'un message entre dans une file de messages vide
référencée par le descripteur de file de messages
mqdes.
L'argument
sevp est un pointeur vers une structure
sigevent. Pour
plus d'informations sur cette structure, consultez
sigevent(7).
Si
sevp est un pointeur non NULL, alors
mq_notify() enregistre le
processus appelant afin de recevoir les notifications. Le champ
sigev_notify de
sigevent qui pointe vers
sevp
spécifie comment la notification est réalisée. Ce champ
possède l'une des valeurs suivantes :
- SIGEV_NONE
- Une notification
« null » : le processus appelant est
enregistré comme destinataire des notifications, mais aucune
notification n'est envoyée lorsqu'un message arrive.
- SIGEV_SIGNAL
- Notifier le processus en envoyant le signal
spécifié dans sigev_signo. Consultez
sigevent(7) pour plus de détails. Le champ si_code de
la structure siginfo_t sera défini à SI_MESGQ.
De plus, si_pid sera défini au PID du processus qui envoie
le message, et si_uid sera défini à l'ID utilisateur
du processus émetteur.
- SIGEV_THREAD
- Jusqu'à la livraison du message, invoquer
sigev_notify_function comme si c'était la fonction de
création d'un nouveau processus léger. Consultez
sigevent(7) pour plus détails.
Seul un processus peut être enregistré pour recevoir les
notifications d'une file de messages.
Si
sevp est NULL, et si le processus appelant est actuellement
enregistré pour recevoir des notifications de cette file de messages,
alors l'enregistrement est supprimé ; un autre processus peut
s'enregistrer pour recevoir les notifications de cette file.
Une notification de message n'est créée que lorsqu'un nouveau
message arrive et que la file est vide. Si la file n'est pas vide à ce
moment,
mq_notify() est appelée, alors une notification sera
créée après que la file est vidée et qu'un nouveau
message arrive.
Si un autre processus ou thread attend pour lire un message d'une file vide avec
mq_receive(3), alors tout enregistrement de notification de message est
ignoré : le message est délivré au processus ou au
thread appelant avec
mq_receive(3) et l'enregistrement de notification
de message garde son effet.
Une notification apparaît une seule fois : après qu'une
notification est délivrée, l'enregistrement de notification est
supprimé et d'autre processus peuvent s'enregistrer. Si le processus
notifié souhaite recevoir la prochaine notification, il peut utiliser
mq_notify() pour demander une autre notification. Cela doit être
fait avant de vider tous les messages non lus de la file (Placer la file en
mode non bloquant est utile pour la vider sans la bloquer une seule fois si
elle est vide).
Si elle réussit, la fonction
mq_notify() renvoie
0. En cas
d'erreur, elle renvoie
-1 et définit
errno en
conséquence.
- EBADF
- Le descripteur de file de messages spécifié
dans mqdes n'est pas valable.
- EBUSY
- Un autre processus est déjà enregistré
pour recevoir les notifications de cette file de messages.
- EINVAL
-
sevp->sigev_notify n'est pas l'une des valeurs
permises ; ou sevp->sigev_notify vaut SIGEV_SIGNAL
et sevp->sigev_signo n'est pas un numéro de signal
valable.
- ENOMEM
- Mémoire insuffisante.
POSIX.1-2008 dit qu'une implémentation
pourrait
générer une erreur
EINVAL si
sevp est NULL et si
l'appelant n'a pas souscrit aux notifications de la file
mqdes.
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
Interface |
Attribut |
Valeur |
mq_notify() |
Sécurité des threads |
MT-Safe |
POSIX.1-2001.
Dans l'implémentation de la glibc, la fonction de bibliothèque
mq_notify() est implémentée au-dessus de l'appel
système du même nom. Quand
sevp est NULL, ou
spécifie un mécanisme de notification autre que
SIGEV_THREAD, la fonction de la bibliothèque invoque directement
l'appel système. Pour
SIGEV_THREAD, l'essentiel de
l'implémentation réside à l'intérieur de la
bibliothèque plutôt que dans le noyau. (Il en est
nécessairement ainsi, dans la mesure où le thread
impliqué dans la gestion de la notification fait partie de ceux qui
doivent être géré par l'implémentation de la
bibliothèque des threads POSIX de C.) La mise en œuvre
implique l'utilisation d'un socket
netlink(7) brut et crée un
nouveau thread pour chaque notification délivrée au processus.
Le programme suivant enregistre une requête de notification pour une file
de messages nommée avec l'un des arguments de la ligne de commande. La
notification est réalisée en créant un thread. Le thread
exécute une fonction qui lit un message provenant de la file puis le
processus se termine.
#include <mqueue.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void /* Thread start function */
tfunc(union sigval sv)
{
struct mq_attr attr;
ssize_t nr;
void *buf;
mqd_t mqdes = *((mqd_t *) sv.sival_ptr);
/* Determine max. msg size; allocate buffer to receive msg */
if (mq_getattr(mqdes, &attr) == -1)
handle_error("mq_getattr");
buf = malloc(attr.mq_msgsize);
if (buf == NULL)
handle_error("malloc");
nr = mq_receive(mqdes, buf, attr.mq_msgsize, NULL);
if (nr == -1)
handle_error("mq_receive");
printf("Lire %zd octets depuis MQ\n", nr);
free(buf);
exit(EXIT_SUCCESS); /* Terminer le processus */
}
int
main(int argc, char *argv[])
{
mqd_t mqdes;
struct sigevent sev;
if (argc != 2) {
fprintf(stderr, "Usage: %s <mq-name>\n", argv[0]);
exit(EXIT_FAILURE);
}
mqdes = mq_open(argv[1], O_RDONLY);
if (mqdes == (mqd_t) -1)
handle_error("mq_open");
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = tfunc;
sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_ptr = &mqdes; /* Arg. to thread func. */
if (mq_notify(mqdes, &sev) == -1)
handle_error("mq_notify");
pause(); /* Le processus sera terminé par la fonction du proc. */
}
mq_close(3),
mq_getattr(3),
mq_open(3),
mq_receive(3),
mq_send(3),
mq_unlink(3),
mq_overview(7),
sigevent(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
<
[email protected]>, Thierry Vignaud
<
[email protected]>, François Micaux, Alain Portal
<
[email protected]>, Jean-Philippe Guérard
<
[email protected]>, Jean-Luc Coulon (f5ibh)
<
[email protected]>, Julien Cristau
<
[email protected]>, Thomas Huriaux <
[email protected]>,
Nicolas François <
[email protected]>, Florentin
Duneau <
[email protected]>, Simon Paillard
<
[email protected]>, Denis Barbier
<
[email protected]>, David Prévot <
[email protected]> et
Jean-Pierre Giraud <
[email protected]>
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 à
[email protected]