POSIX Message Queues

Ce forum est dédié à apprendre le développement de programmes user mode sur Linux

Moderator: Rick

Post Reply
Hydraxx
Site Admin
Posts: 114
Joined: Mon Jan 12, 2026 4:04 pm
Location: France
Contact:

POSIX Message Queues

Post by Hydraxx »

POSIX Message Queues

1. Introduction

Les POSIX Message Queues permettent à plusieurs processus d'échanger des données sous forme de messages complets.

Contrairement à un pipe, une file de messages ne représente pas simplement un flux continu d'octets.

Chaque appel à mq_send() ajoute un message distinct.

Chaque appel à mq_receive() récupère un message complet.

Les POSIX Message Queues sont similaires aux files de messages System V, mais elles possèdent plusieurs caractéristiques particulières :
  • utilisation d'un nom POSIX ;
  • utilisation d'un descripteur de type mqd_t ;
  • gestion de priorités ;
  • possibilité de fonctionnement bloquant ou non bloquant ;
  • possibilité d'utiliser des délais d'attente ;
  • possibilité de demander une notification asynchrone lorsqu'un message arrive.

2. Vue d'ensemble de l'API

Fonctions principales

Code: Select all

mq_open()
Crée une nouvelle file de messages ou ouvre une file existante.

Code: Select all

mq_close()
Ferme un descripteur de file de messages.

Code: Select all

mq_unlink()
Supprime le nom d'une file de messages.

Code: Select all

mq_send()
Ajoute un message dans une file.

Code: Select all

mq_receive()
Retire un message d'une file.

Code: Select all

mq_getattr()
Récupère les attributs associés à une file de messages.

Code: Select all

mq_setattr()
Modifie certains attributs associés au descripteur.

Code: Select all

mq_notify()
Demande une notification lorsqu'un message devient disponible.

Code: Select all

mq_timedsend()
Version de mq_send() avec timeout.

Code: Select all

mq_timedreceive()
Version de mq_receive() avec timeout.


3. Création et ouverture d'une file

mq_open()

Prototype simplifié :

Code: Select all

mqd_t mq_open(
    const char *name,
int oflag,
...
);

Lorsque O_CREAT est utilisé, deux arguments supplémentaires peuvent être fournis :

mode_t mode

et :

Code: Select all

struct mq_attr *attr
Exemple :

Code: Select all

mqd_t mq = mq_open(
"/inside_queue",

Code: Select all

    O_CREAT | O_RDWR,
0666,
NULL
);


Valeur de retour

Code: Select all

mq_open() retourne un descripteur de type :

mqd_t
En cas d'erreur :

(mqd_t)-1


4. Nom d'une file POSIX

Les files de messages POSIX utilisent des noms.

Exemple :

"/inside_queue"

Sur Linux, un nom POSIX doit commencer par :

Code: Select all

/
Le nom permet à plusieurs processus indépendants d'ouvrir la même file.

Exemple :

Processus A :

Code: Select all

mq_open("/inside_queue", ...);
Processus B :

Code: Select all

mq_open("/inside_queue", ...);
Les deux processus peuvent alors accéder au même objet noyau.


5. Flags de mq_open()

O_RDONLY

Ouvre la file uniquement en lecture.

Le processus pourra utiliser :

Code: Select all

mq_receive()
O_WRONLY

Ouvre la file uniquement en écriture.

Le processus pourra utiliser :

Code: Select all

mq_send()
O_RDWR

Ouvre la file en lecture et en écriture.


O_CREAT

Crée la file si elle n'existe pas.


O_EXCL

Utilisé avec O_CREAT.

Si la file existe déjà, mq_open() échoue.

Exemple :

Code: Select all

O_CREAT | O_EXCL | O_RDWR
O_NONBLOCK

Active le fonctionnement non bloquant.

Une opération qui devrait normalement attendre échoue immédiatement.


6. Permissions

Lors de la création d'une file, le paramètre mode permet de choisir les permissions.

Exemple :

Code: Select all

0666
Les permissions ressemblent aux permissions classiques des fichiers Unix.

Elles sont également affectées par le umask du processus.


7. Fermeture d'une file

mq_close()

Prototype :

Code: Select all

int mq_close(mqd_t mqdes);

mq_close() ferme le descripteur détenu par le processus.
Exemple :

Code: Select all

mq_close(mq);
Cela ne supprime pas forcément la file.

La file peut toujours exister et être ouverte par d'autres processus.


8. Suppression d'une file

mq_unlink()

Prototype :

Code: Select all

int mq_unlink(const char *name);
Exemple :

Code: Select all

mq_unlink("/inside_queue");

mq_unlink() supprime le nom de la file.
Si des processus possèdent encore des descripteurs ouverts vers cette file, ils peuvent continuer à l'utiliser.

L'objet est réellement détruit lorsque :
  • son nom a été supprimé ;
  • aucun processus ne possède encore de référence ouverte.
Ce comportement ressemble au mécanisme unlink() des fichiers Unix.


9. Descripteurs de files POSIX

Le type utilisé pour représenter une file ouverte est :

Code: Select all

mqd_t
Chaque appel réussi à mq_open() retourne un descripteur.

Sur Linux, ce descripteur est étroitement intégré au modèle des descripteurs de fichiers.

Un fork() fait hériter au processus fils des descripteurs ouverts.

Le parent et le fils peuvent donc référencer la même description de file ouverte après fork().


10. Relation entre processus, descripteurs et file

Plusieurs processus peuvent ouvrir le même objet POSIX.

Par exemple :

Processus A
|
+--> mqd_t
|
+--> File POSIX

Processus B
|
+--> mqd_t
|
+--> Même file POSIX

Chaque processus possède son propre descripteur.

Cependant, les deux descripteurs peuvent désigner le même objet de file maintenu par le noyau.


11. Attributs d'une file de messages

Les propriétés d'une file sont représentées par :

Code: Select all

struct mq_attr
Structure conceptuelle :

Code: Select all

struct mq_attr {
long mq_flags;
long mq_maxmsg;
long mq_msgsize;
long mq_curmsgs;

Code: Select all

};
mq_flags

Contient les flags associés au descripteur.

Sur Linux, l'information importante est généralement :

Code: Select all

O_NONBLOCK
mq_maxmsg

Nombre maximal de messages pouvant être présents simultanément dans la file.


mq_msgsize

Taille maximale, en octets, d'un seul message.


mq_curmsgs

Nombre actuel de messages présents dans la file.


12. Définir les attributs lors de la création

Lorsqu'une file est créée avec mq_open(), un pointeur vers struct mq_attr peut être fourni.

Exemple :

Code: Select all

struct mq_attr attr;

attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 2048;
attr.mq_curmsgs = 0;

mqd_t mq = mq_open(
"/queue",

Code: Select all

    O_CREAT | O_RDWR,
0666,
&attr
);

Lors de la création, les deux champs particulièrement importants sont :

mq_maxmsg

et :

mq_msgsize

mq_curmsgs est déterminé par le noyau.

mq_flags concerne plutôt le comportement du descripteur.


13. Récupérer les attributs

mq_getattr()

Prototype :

Code: Select all

int mq_getattr(
    mqd_t mqdes,
    struct mq_attr *attr
);

Exemple :

Code: Select all

struct mq_attr attr;

if (mq_getattr(mq, &attr) == -1) {
    perror("mq_getattr");
}

printf("Maximum messages : %ld\n", attr.mq_maxmsg);
printf("Taille maximale : %ld\n", attr.mq_msgsize);
printf("Messages présents : %ld\n", attr.mq_curmsgs);
Cette fonction permet notamment de connaître la taille de buffer nécessaire pour mq_receive().


14. Modifier les attributs

mq_setattr()

Prototype :

Code: Select all

int mq_setattr(
    mqd_t mqdes,
const struct mq_attr *newattr,

Code: Select all

    struct mq_attr *oldattr
);

Code: Select all

mq_setattr() ne permet pas de changer librement tous les champs.
L'utilisation principale consiste à modifier le flag :

Code: Select all

O_NONBLOCK
Exemple

Code: Select all

struct mq_attr attr;

mq_getattr(mq, &attr);

attr.mq_flags |= O_NONBLOCK;

mq_setattr(mq, &attr, NULL);
15. Envoi d'un message

mq_send()

Prototype :

Code: Select all

int mq_send(
    mqd_t mqdes,
    const char *msg_ptr,
size_t msg_len,

Code: Select all

    unsigned int msg_prio
);

Exemple :

Code: Select all

const char *msg = "Inside The System";

mq_send(
mq,
msg,
strlen(msg) + 1,
5
);


Paramètres

mqdes

Descripteur de la file.


msg_ptr

Adresse du message à envoyer.


msg_len

Longueur du message.


msg_prio

Priorité du message.


16. Taille maximale d'un message

Le paramètre msg_len ne doit pas dépasser :

mq_msgsize

Si le message est trop grand, mq_send() échoue.

La taille maximale peut être récupérée avec :

Code: Select all

mq_getattr()
17. Priorités

Chaque message POSIX possède une priorité entière non négative.

Exemple :

Code: Select all

mq_send(mq, "LOW", 4, 1);

mq_send(mq, "HIGH", 5, 10);
Le message ayant la priorité la plus élevée est reçu en premier.

À priorité identique, les messages conservent leur ordre d'arrivée.

On obtient donc globalement :

priorité la plus élevée d'abord

puis :

FIFO pour les messages ayant la même priorité.


18. Différence avec System V pour la sélection des messages

Avec System V, on utilise souvent un champ :

long mtype;

Le récepteur peut sélectionner un message selon ce type.

Avec POSIX, les messages utilisent directement un niveau de priorité.

Il n'existe donc pas exactement le même mécanisme que mtype.

La sélection se fait selon la priorité puis l'ordre d'arrivée.


19. Comportement lorsque la file est pleine

Si la file contient déjà :

mq_maxmsg

messages, elle est pleine.

Avec un descripteur bloquant :

Code: Select all

mq_send()
attend qu'une place se libère.

Avec :

Code: Select all

O_NONBLOCK

mq_send() échoue immédiatement.
L'erreur typique est :

Code: Select all

EAGAIN
20. Réception d'un message

mq_receive()

Prototype :

Code: Select all

ssize_t mq_receive(
    mqd_t mqdes,
    char *msg_ptr,
size_t msg_len,

Code: Select all

    unsigned int *msg_prio
);

Exemple :

Code: Select all

struct mq_attr attr;

mq_getattr(mq, &attr);

char *buffer = malloc(attr.mq_msgsize);

unsigned int priority;

ssize_t size = mq_receive(
mq,
buffer,

Code: Select all

    attr.mq_msgsize,
&priority
);


Valeur de retour

En cas de succès :

nombre d'octets reçus.

En cas d'erreur :

Code: Select all

-1
21. Taille du buffer de réception

Le buffer fourni à mq_receive() doit être assez grand pour contenir la taille maximale autorisée pour un message dans la file.

En pratique, on peut faire :

Code: Select all

struct mq_attr attr;

mq_getattr(mq, &attr);

char *buffer = malloc(attr.mq_msgsize);
Puis :

Code: Select all

mq_receive(
mq,
buffer,

Code: Select all

    attr.mq_msgsize,
&priority
);

Si le buffer est trop petit, l'appel échoue.


22. Priorité du message reçu

Le dernier argument de mq_receive() permet de récupérer la priorité.

Exemple :

Code: Select all

unsigned int priority;

mq_receive(
mq,
buffer,
size,
&priority
);

Après l'appel :

priority

contient la priorité du message reçu.

Si cette information n'est pas nécessaire, il est possible d'utiliser :

NULL


23. File vide

Si la file ne contient aucun message :

Code: Select all

mq_receive()
bloque normalement jusqu'à l'arrivée d'un message.

Avec :

Code: Select all

O_NONBLOCK
l'appel échoue immédiatement avec :

Code: Select all

EAGAIN
24. Mode bloquant

Par défaut, une file est généralement utilisée en mode bloquant.

Exemple :

Code: Select all

mq_receive(...);
Si aucun message n'est présent, le thread attend.

De même :

Code: Select all

mq_send(...);
peut attendre si la file est pleine.

Ce comportement est pratique lorsqu'on souhaite naturellement synchroniser producteur et consommateur.


25. Mode non bloquant

Le flag :

Code: Select all

O_NONBLOCK
désactive cette attente.

Exemple :

Code: Select all

mq_open(
"/queue",

Code: Select all

    O_RDONLY | O_NONBLOCK
);

Si aucun message n'est disponible :

Code: Select all

mq_receive()
retourne -1 avec :

Code: Select all

errno == EAGAIN
Cela permet au programme de continuer son travail au lieu d'être endormi.


26. Envoi avec timeout

mq_timedsend()

Prototype conceptuel :

Code: Select all

int mq_timedsend(
    mqd_t mqdes,
    const char *msg_ptr,
size_t msg_len,

Code: Select all

    unsigned int msg_prio,
const struct timespec *abs_timeout
);

Cette fonction fonctionne comme mq_send(), mais permet de limiter le temps d'attente.

Si la file est pleine et qu'aucune place ne devient disponible avant l'échéance :

Code: Select all

mq_timedsend()
échoue.


27. Réception avec timeout

mq_timedreceive()

Prototype conceptuel :

Code: Select all

ssize_t mq_timedreceive(
    mqd_t mqdes,
    char *msg_ptr,
size_t msg_len,

Code: Select all

    unsigned int *msg_prio,
const struct timespec *abs_timeout
);

Cette fonction fonctionne comme mq_receive(), mais l'attente possède une limite temporelle.

Si aucun message n'arrive avant l'échéance :

Code: Select all

mq_timedreceive()
échoue généralement avec :

Code: Select all

ETIMEDOUT
28. Timeout absolu

Les fonctions temporisées utilisent un :

Code: Select all

struct timespec
représentant une échéance absolue.

On peut récupérer l'heure actuelle puis ajouter un délai.

Exemple conceptuel :

Code: Select all

struct timespec ts;

clock_gettime(CLOCK_REALTIME, &ts);

ts.tv_sec += 5;

mq_timedreceive(
mq,
buffer,
size,
&priority,
&ts
);

Le processus attend au maximum jusqu'à cette échéance.


29. Notification de message

Une fonctionnalité importante des POSIX Message Queues est :

Code: Select all

mq_notify()
Elle permet à un processus de demander au noyau d'être prévenu lorsqu'un message devient disponible dans une file.


Prototype

Code: Select all

int mq_notify(
    mqd_t mqdes,
const struct sigevent *notification
);


30. Principe de mq_notify()

L'idée est la suivante :

1. Le processus ouvre une file.

2. Il appelle mq_notify().

3. Il demande au noyau de le prévenir lorsqu'un message arrive.

4. Le processus peut effectuer autre chose.

5. Lorsqu'un message devient disponible, le mécanisme demandé est déclenché.

Cela évite de rester bloqué en permanence dans mq_receive().


31. Une seule inscription à la fois

Une seule inscription de notification peut être active pour une file donnée.

Si un autre processus tente d'enregistrer une notification alors qu'une inscription existe déjà, l'appel échoue.

Cela impose de coordonner les consommateurs lorsque plusieurs processus utilisent la même file.


32. Notification ponctuelle

Une caractéristique importante de mq_notify() est que l'inscription est généralement ponctuelle.

Après qu'une notification a été déclenchée, le processus doit s'enregistrer à nouveau s'il souhaite continuer à recevoir des notifications.

Le schéma classique est donc :

Code: Select all

mq_notify()


notification



lecture des messages


Code: Select all

mq_notify() de nouveau
33. struct sigevent

Le comportement de mq_notify() est choisi avec :

Code: Select all

struct sigevent
Cette structure peut notamment demander :
  • aucune notification ;
  • l'envoi d'un signal ;
  • l'exécution d'une fonction via un thread.

34. SIGEV_NONE

Avec :

Code: Select all

SIGEV_NONE
aucune notification réelle n'est générée.

Le processus peut néanmoins utiliser cette valeur dans certains contextes pour gérer l'enregistrement.


35. SIGEV_SIGNAL

Avec :

Code: Select all

SIGEV_SIGNAL
le noyau envoie un signal au processus lorsqu'un message devient disponible.

Exemple conceptuel :

Code: Select all

struct sigevent sev;

sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;

mq_notify(mq, &sev);
Lorsqu'un message arrive, le processus reçoit :

SIGUSR1


36. sigev_value

Code: Select all

struct sigevent peut également transporter une valeur définie par le programme.
Cette valeur est stockée dans :

sigev_value

Elle peut ensuite être récupérée par certains mécanismes de notification.

Cela permet de transmettre du contexte au gestionnaire de notification.


37. SIGEV_THREAD

Avec :

Code: Select all

SIGEV_THREAD
le système peut appeler une fonction dans un thread lorsque la notification se produit.

Exemple conceptuel :

Code: Select all

struct sigevent sev;

sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = handler;
sev.sigev_notify_attributes = NULL;

mq_notify(mq, &sev);
La fonction :

handler()

sera exécutée lors de la notification.


38. Course critique avec mq_notify()

L'utilisation de mq_notify() nécessite une certaine prudence.

Un schéma important consiste souvent à réenregistrer la notification avant de vider complètement la file.

Sinon, un message peut arriver entre :
  • la dernière lecture ;
  • le nouvel appel à mq_notify().
Cela pourrait entraîner une notification manquée.

L'ordre des opérations est donc important dans un programme concurrent.


39. Lecture de tous les messages après notification

Une stratégie fréquente est :

1. recevoir une notification ;

2. réenregistrer mq_notify() ;

3. lire tous les messages disponibles ;

4. arrêter lorsque mq_receive() retourne EAGAIN.

Pour cette stratégie, la file est généralement ouverte avec :

Code: Select all

O_NONBLOCK
Ainsi, le programme peut facilement détecter lorsque la file est vide.


40. Exemple simplifié d'envoi

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <mqueue.h>

int main(void)
{
    mqd_t mq;
mq = mq_open(
"/inside_queue",

Code: Select all

        O_CREAT | O_WRONLY,
0666,
NULL
);

Code: Select all

    if (mq == (mqd_t)-1) {
        perror("mq_open");
        return EXIT_FAILURE;
    }

    const char *message = "Inside The System";

    if (mq_send(
mq,
message,
strlen(message) + 1,
10
) == -1) {

Code: Select all

        perror("mq_send");
    }

    mq_close(mq);

    return EXIT_SUCCESS;
}
41. Exemple simplifié de réception

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <mqueue.h>

int main(void)
{
    mqd_t mq;
    struct mq_attr attr;
mq = mq_open(
"/inside_queue",

Code: Select all

        O_RDONLY
);

Code: Select all

    if (mq == (mqd_t)-1) {
        perror("mq_open");
        return EXIT_FAILURE;
    }

    if (mq_getattr(mq, &attr) == -1) {
        perror("mq_getattr");
        mq_close(mq);
        return EXIT_FAILURE;
    }

    char *buffer = malloc(attr.mq_msgsize);

    if (buffer == NULL) {
        perror("malloc");
        mq_close(mq);
        return EXIT_FAILURE;
    }

    unsigned int priority;

    ssize_t n = mq_receive(
mq,
buffer,

Code: Select all

        attr.mq_msgsize,
&priority
);

Code: Select all

    if (n == -1) {
        perror("mq_receive");
    } else {
        printf("Message : %s\n", buffer);
        printf("Priorité : %u\n", priority);
    }

    free(buffer);
    mq_close(mq);

    return EXIT_SUCCESS;
}
42. Suppression propre

Après utilisation :

Code: Select all

mq_close(mq);
Puis, lorsque la file n'est plus nécessaire :

Code: Select all

mq_unlink("/inside_queue");
Il est important de distinguer :

Code: Select all

mq_close()
et :

Code: Select all

mq_unlink()

mq_close() ferme une référence.

mq_unlink() retire le nom de l'objet.
43. POSIX Message Queues sous Linux

Sous Linux, les files POSIX peuvent être représentées dans un système de fichiers virtuel.

Le point de montage généralement utilisé est :

Code: Select all

/dev/mqueue
Une fois monté, les files peuvent apparaître sous forme d'entrées visibles dans ce répertoire.


Montage

Exemple :

Code: Select all

mount -t mqueue none /dev/mqueue
Observation

On peut ensuite utiliser des commandes classiques comme :

Code: Select all

ls /dev/mqueue

cat /dev/mqueue/nom_de_file
La représentation fournie permet d'obtenir certaines informations sur la file.


44. Informations visibles dans /dev/mqueue

Sous Linux, les informations exposées peuvent inclure notamment :
  • quantité de données actuellement présente ;
  • informations concernant une notification ;
  • PID du processus enregistré pour la notification ;
  • type de notification.
Cela permet d'inspecter plus facilement l'état des files POSIX depuis l'espace utilisateur.


45. Limites système

Les files de messages POSIX possèdent plusieurs limites.

Exemples :
  • nombre maximal de files ;
  • nombre maximal de messages par file ;
  • taille maximale d'un message ;
  • priorité maximale.

MQ_PRIO_MAX

Cette limite correspond au nombre de niveaux de priorité disponibles.

POSIX impose un minimum portable.

Linux peut proposer une plage différente ou plus grande selon l'implémentation.


OPEN_MAX

Cette valeur concerne le nombre maximal de descripteurs ouverts qu'un processus peut posséder.

Les descripteurs de files POSIX peuvent compter dans ces limites selon l'implémentation.


46. Limites Linux

Linux expose plusieurs paramètres permettant de contrôler les ressources utilisées par les POSIX Message Queues.

Ces limites peuvent concerner :
  • la taille maximale d'un message ;
  • le nombre maximal de messages par file ;
  • le nombre maximal de files ;
  • la quantité totale de mémoire utilisée.
Certaines limites sont configurables via des interfaces système Linux.


47. Comparaison avec System V

Les deux mécanismes permettent d'échanger des messages entre processus.

Mais leur conception diffère.


System V

Fonctions principales :

msgget()
msgsnd()
msgrcv()
msgctl()

Identifiant :

int

Sélection des messages :

mtype

Suppression :

msgctl(..., IPC_RMID, ...)


POSIX

Fonctions principales :

Code: Select all

mq_open()
mq_send()
mq_receive()
mq_close()
mq_unlink()
Identifiant :

Code: Select all

mqd_t
Ordonnancement :

priorité

Suppression du nom :

Code: Select all

mq_unlink()
48. Avantages des POSIX Message Queues

Les files POSIX possèdent plusieurs avantages.
  • API relativement cohérente avec le reste de POSIX.
  • Noms lisibles.
  • Priorités intégrées.
  • Notification asynchrone.
  • Mode non bloquant.
  • Fonctions temporisées.
  • Bonne intégration avec Linux.
  • Possibilité d'inspection via /dev/mqueue.

49. Inconvénients

Quelques limites existent également.
  • Elles ne sont pas disponibles ou identiques sur tous les systèmes Unix.
  • Leur portabilité pratique peut être inférieure à celle d'autres mécanismes POSIX très répandus.
  • Les limites maximales peuvent varier selon le système.
  • Leur utilisation avec notifications demande une bonne gestion des courses critiques.
  • Pour de très gros volumes de données, la mémoire partagée peut être plus adaptée.

50. Choix entre pipe, message queue et mémoire partagée

Pipe

Adapté à un flux simple entre processus.

Exemple :

producteur -> consommateur


Message queue

Adaptée lorsque les données doivent rester séparées en messages.

Particulièrement utile si :
  • plusieurs messages doivent être mis en attente ;
  • des priorités sont nécessaires ;
  • une notification est utile.

Mémoire partagée

Adaptée pour échanger rapidement de grandes quantités de données.

Elle nécessite cependant généralement un mécanisme supplémentaire de synchronisation.


51. Schéma général d'utilisation

Création :

Code: Select all

mq_open()


Configuration éventuelle :

Code: Select all

mq_getattr()
mq_setattr()


Communication :

Code: Select all

mq_send()
mq_receive()
ou :

Code: Select all

mq_timedsend()
mq_timedreceive()


Notification éventuelle :

Code: Select all

mq_notify()


Fermeture :

Code: Select all

mq_close()


Suppression :

Code: Select all

mq_unlink()
52. Points importants à retenir

Une POSIX Message Queue conserve des messages distincts.

La fonction :

Code: Select all

mq_open()
crée ou ouvre une file.

Le type du descripteur est :

Code: Select all

mqd_t
Les fonctions :

Code: Select all

mq_send()
et :

Code: Select all

mq_receive()
permettent d'échanger les messages.

Les messages possèdent une priorité.

La priorité la plus élevée est reçue en premier.

À priorité égale, l'ordre reste FIFO.

Les attributs sont décrits par :

Code: Select all

struct mq_attr
avec notamment :

mq_flags
mq_maxmsg
mq_msgsize
mq_curmsgs

Code: Select all

mq_getattr() récupère ces informations.

mq_setattr() permet principalement de modifier le comportement O_NONBLOCK.
Avec O_NONBLOCK :
  • mq_send() ne bloque pas si la file est pleine ;
  • mq_receive() ne bloque pas si la file est vide.
Dans ce cas, l'erreur :

Code: Select all

EAGAIN
peut être retournée.

Les fonctions :

Code: Select all

mq_timedsend()
et :

Code: Select all

mq_timedreceive()
permettent d'ajouter une limite temporelle.

Code: Select all

mq_notify() permet de recevoir une notification lorsqu'un message devient disponible.
Cette notification peut notamment utiliser :

Code: Select all

SIGEV_SIGNAL
ou :

Code: Select all

SIGEV_THREAD
L'enregistrement mq_notify() est ponctuel et doit généralement être renouvelé après déclenchement.

Code: Select all

mq_close() ferme un descripteur.

mq_unlink() supprime le nom de la file.
Sous Linux, les POSIX Message Queues peuvent être observées dans :

Code: Select all

/dev/mqueue
53. Résumé

Les POSIX Message Queues constituent un mécanisme IPC permettant d'échanger des messages structurés entre processus.

Elles sont ouvertes avec mq_open() et représentées par des descripteurs de type mqd_t.

Les messages sont envoyés avec mq_send() et reçus avec mq_receive().

Chaque message possède une priorité, ce qui permet au noyau de délivrer en premier les messages les plus importants.

Le comportement bloquant peut être modifié avec O_NONBLOCK.

Les fonctions temporisées permettent d'éviter une attente infinie.

Le mécanisme mq_notify() permet de transformer une file en mécanisme plus événementiel, en prévenant le processus lorsqu'un nouveau message devient disponible.

Enfin, mq_close() et mq_unlink() séparent clairement la fermeture d'un descripteur et la suppression du nom de l'objet.

Les POSIX Message Queues sont donc particulièrement adaptées aux communications entre processus lorsque l'on souhaite conserver les frontières des messages, gérer des priorités ou recevoir des notifications asynchrones.

Who is online

Users browsing this forum: No registered users and 1 guest