0. Qu'est-ce qu'une file d'attente de messages
La file d'attente de messages peut être considérée comme une liste de messages. Les threads peuvent placer des messages dans la file d'attente de messages ou retirer des messages. Chaque message est un enregistrement, prioritaire par l'expéditeur. Un processus n'a pas besoin d'attendre qu'un message arrive dans la file d'attente avant d'écrire un message dans une file d'attente de messages (c'est le contraire des tubes et des FIFO).
La file d'attente de messages a une persistance avec le noyau, c'est-à-dire qu'avant le redémarrage du noyau, la file d'attente de messages existera toujours indépendamment du fait que le processus d'envoi ou de récupération de message se termine.
Il existe deux types de files d'attente de messages, la file d'attente de messages Posix et la file d'attente de messages System V. L'exemple suivant est l'utilisation de la file d'attente de messages Posix.
1. Ouvrez (ou créez), fermez la file d'attente des messages
// 1.c
#include<stdio.h>
#include<mqueue.h>
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
int main(int argc, char* argv[])
{
int flag;
mqd_t mdq;
flag = O_RDWR | O_CREAT;
if (argc < 2) {
printf("Please input mqueue name!\n");
}
// NULL 表示采用默认属性
mdq = mq_open(argv[1], flag, FILE_MODE, NULL);
return 0;
}
Ce qui précède est une routine pour créer une file d'attente de messages. Utilisez la commande suivante pour compiler et obtenir le fichier exécutable a.out
gcc -g 1.c -Wall -lrt
Exécutez la commande suivante, vous pouvez obtenir une file d'attente de messages nommée temp.1234, qui est stockée dans / dev / mqueue
./a.out /temp.1234
[root@localhost IPC]# ll /dev/mqueue/
total 0
-rw-r--r--. 1 root root 80 Nov 9 06:59 temp.1234
Notez que le nom de la file d'attente de messages doit commencer par un «/» pour être créé avec succès.
2. Supprimez la file d'attente des messages
Pour supprimer la file d'attente de messages, utilisez la fonction mq_unlink.
// 2.c
#include<stdio.h>
#include<mqueue.h>
int main(int argc, char* argv[])
{
if (argc < 2) {
printf("Please input mqueue name!\n");
}
int ret = mq_unlink(argv[1]);
printf("%d\n", ret);
return 0;
}
Compiler
gcc -g 2.c -Wall -lrt
effectué
./a.out /temp.1234
Après l'exécution, vous pouvez voir que la file d'attente de messages qui vient d'être créée a été supprimée.
[root@localhost IPC]# ll /dev/mqueue/
total 0
3. obtenir / définir les propriétés de la file d'attente de messages
Chaque file d'attente de messages a quatre attributs et la fonction mq_getattr renvoie tous ces attributs.
struct mq_attr {
long mq_flags;
long mq_maxmsg; //消息队列上最多可以存储的消息数目
long mq_msgsize; //一条消息最多可以容纳多少字节
long mq_curmsgs; //当前队列中存储的消息数量
};
// 3.c
#include<stdio.h>
#include<mqueue.h>
int main(int argc, char* argv[])
{
mqd_t mqd;
struct mq_attr attr;
if (argc < 2) {
printf("Please input mqueue name!\n");
}
mqd = mq_open(argv[1], O_RDONLY);
mq_getattr(mqd, &attr);
printf("max msgs = %ld\nmax bytes/msg = %ld\ncurrently on queue = %ld\n",
attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
mq_close(mqd);
return 0;
}
Compilez et exécutez, affichez les propriétés de la file d'attente de messages que nous venons de créer
gcc -g 3.c -Wall -lrt
./a.out /temp.1234
max msgs = 10
max bytes/msg = 8192
currently on queue = 0
Vous pouvez voir que la file d'attente de messages que nous avons créée peut contenir jusqu'à 10 messages, chaque message a un maximum de 8192 octets et il n'y a aucun message dans la file d'attente actuelle.
La fonction mq_setattr définit les attributs de la file d'attente, mais n'utilise que le champ mq_flags de la structure mq_attr pour définir ou effacer le bit d'indicateur non bloquant. Les trois autres membres de cette structure sont ignorés.
Si vous souhaitez définir le nombre maximum de messages et le nombre maximum d'octets par message, vous devez les spécifier lors de la création de la file d'attente.
4. Créez une file d'attente avec les attributs spécifiés
Dans l'exemple précédent, le nombre maximal de messages qu'une file d'attente créée avec les attributs par défaut peut contenir est de 10 et chaque message a un maximum de 8 192 octets. Maintenant, nous essayons de créer une file d'attente avec les attributs que nous spécifions.
// 4.c
#include<stdio.h>
#include<mqueue.h>
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
struct mq_attr attr;
int main(int argc, char* argv[])
{
int flag;
mqd_t mdq;
flag = O_RDWR | O_CREAT;
if (argc < 2) {
printf("Please input mqueue name!\n");
return -1;
}
attr.mq_maxmsg = 20;
attr.mq_msgsize = 4096;
mdq = mq_open(argv[1], flag, FILE_MODE, &attr);
mq_close(mdq);
return 0;
}
Dans cet exemple, nous définissons le nombre maximum de messages sur 20, et chaque message a un maximum de 4096 octets.
Compilez et exécutez et vérifiez les propriétés
max msgs = 20
max bytes/msg = 4096
currently on queue = 0
Comme vous pouvez le voir, cette fois, nous avons créé une file d'attente de messages différente.
5. fonction mq_send / mq_receive
Ces deux fonctions sont utilisées pour ajouter et supprimer des messages dans une file d'attente. Chaque message a une priorité, mq_receive renvoie toujours le message le plus ancien avec la priorité la plus élevée dans la file d'attente, et la priorité peut être renvoyée avec le contenu et la longueur du message.
envoyer
// send
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<mqueue.h>
int main(int argc, char* argv[])
{
int priorty;
mqd_t mqd;
if (argc != 4) {
printf("usage: send <name> <message> <priorty>n");
return -1;
}
priorty = atoi(argv[3]);
mqd = mq_open(argv[1], O_WRONLY);
int ret = mq_send(mqd, argv[2], strlen(argv[2]), priorty);
if (ret != 0) {
printf("send message error!\n");
}
mq_close(mqd);
return 0;
}
recevoir
// receive
#include<stdio.h>
#include<stdlib.h>
#include<mqueue.h>
struct mq_attr attr;
int main(int argc, char* argv[])
{
unsigned int priorty, cnt;
mqd_t mqd;
void* buff;
if (argc != 2) {
printf("usage: mqrece <name> \n");
return -1;
}
mqd = mq_open(argv[1], O_RDONLY);
mq_getattr(mqd, &attr);
printf("size = %ld\n", attr.mq_msgsize);
buff = malloc(attr.mq_msgsize);
cnt = mq_receive(mqd, buff, attr.mq_msgsize, &priorty);
printf("received %d bytes, priority = %u\n", cnt, priorty);
printf("message = %s\n", (char*)buff);
mq_close(mqd);
return 0;
}
6. Limite de la file d'attente des messages
L'implémentation de la file d'attente de messages définit deux restrictions:
- MQ_OPEN_MAX Le nombre maximum de files d'attente de messages qu'un processus peut ouvrir en même temps (Posix nécessite un minimum de 8)
- MQ_PRIO_MAX La valeur de priorité maximale de tout message plus 1 (Posix nécessite au moins 32)
Ces deux valeurs sont généralement définies dans <unistd.h> et peuvent être obtenues via la fonction sysconf
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("MQ_OPEN_MAX = %ld\nMQ_PRIO_MAX = %ld\n", sysconf(_SC_MQ_OPEN_MAX), sysconf(_SC_MQ_PRIO_MAX));
return 0;
}
Le résultat de l'exécution sous Linux est
MQ_OPEN_MAX = -1
MQ_PRIO_MAX = 32768
-1 signifie qu'il n'y a pas de limite à la quantité