3. Message Queuing
3.1 Système V IPC
(1) Vue d'ensemble du système V IPC
Le dispositif de communication inter-processus de base mécanisme de signal de présence, et des canaux nommés, etc. système de tuyauterie ①Unix.
②System V présente un mécanisme de communication entre les trois processus de haut niveau : la file d' attente de messages et à partager le sémaphore partagé .
objet ③IPC (files d'attente de messages, les sémaphores et la mémoire partagée) est présent dans le noyau plutôt que le système de fichiers , la libération contrôlée par l'utilisateur (l'objet de gestion du cycle de vie de l' utilisateur ipc), contrairement à la conduite de libération contrôlée par le noyau.
objet ④IPC référencé par l' identification et l' accès à tous les objets IPC dans l' espace noyau a une identification unique ID , dans l'espace utilisateur de l' identification unique de l'appelé clé .
⑤Linux IPC hérité de System V IPC
Accès (2) des objets System V IPC
objet ①IPC est un objet global: IPCS disponibles, les commandes picrm à afficher ou supprimer .
② Chaque IPC objets créés par la fonction get: msgget, shmget, semget. clé mot-clé doit être spécifiée lors de l'appel de la fonction get.
Autorisations et propriétaire de la structure (3) objets IPC
3.2 Message Queuing
(1) Introduction file de messages
① file d' attente de messages est une liste chaînée de noyau ;
② Le processus utilisateur transfère les données vers le noyau, le noyau de rajouter en tant ID utilisateur, ID de groupe, l'ID processus de lecture et informations relatives à la priorité et encapsulé dans un paquet de message de données appelé.
③ permet à un ou plusieurs processus de messages d'écriture dans la file d' attente de message et lire le message, mais le message ne peut être un processus de lecture, la lecture est automatiquement supprimée après la fin.
④ file d' attente de messages a une certaines caractéristiques FIFO , l'ordre peut être envoyé à la file d' attente de messages, de plusieurs façons différentes peuvent être lues à partir de la file d' attente. Chaque message IPC file d' attente d' une identification unique ID exprimée par le noyau .
⑤ mettre en œuvre le message file d'attente comprend une file d'attente création et ouverture, envoyer un message, lire un message et une file d'attente de messages de commande quatre opérations.
(2) la structure de la file d'attente de message (les msqid_ds)
(3) ouvrir et créer une file d'attente de messages
En-tête |
#include <sys / msg.h> |
fonction |
int msgget (key_t clé, drapeau int); |
paramètres |
clé: la file d' attente de message spécifié clé utilisateur Drapeau : IPC_CREAT, et d' autres combinaisons de privilèges IPC_EXCL |
fonction |
Ouvrez ou créez une file d'attente de messages |
La valeur de retour |
Noyau de retour réussi identificateur de file de messages ID, Error -1 |
remarque |
① Pour créer une file d'attente de messages, la clé peut spécifier la clé, il peut également être réglé sur IPC_PRIVATE. ② Si vous ouvrez une requête, la clé ne peut pas être égale à zéro, doit être une valeur non nulle, sinon il ne peut pas trouver. |
(4) un message de contrôle file d'attente
En-tête |
#include <sys / msg.h> |
fonction |
int msgctl (int msgqid, int cmd, msqid_ds struct * buf); |
paramètres |
msgqid : Message Queue ID buf : une file d'attente d'attributs de message de pointeur cmd : (1) IPC_STAT: Obtenir les attributs de la file d'attente de messages, en prenant msqid_ds structurer cette file d'attente, et le stocker dans buf structure spécifiée. (2) IPC_SET: Propriétés réglé, en fonction de la valeur de buf structure pointée, à condition que la file d'attente associée à cette structure de champ. (3) IPC_RMID: supprimer une file d'attente, la file d'attente de message et supprimer toutes les données est encore dans la file d'attente du système. |
fonction |
Un message de contrôle file d'attente |
La valeur de retour |
0 renvoie avec succès, une erreur -1 |
(5) envoie un message
En-tête |
#include <sys / msg.h> |
fonction |
int msgsnd (int msgqid, void * ptr const, nbytes size_t, drapeau int); |
paramètres |
le msqid : Message Queue ID PTR : structure définie par l' utilisateur, mais les premiers membres doivent être mtype. mymesg struct { longue mtype; // type de message positif, le type de message, et ne peut être supérieur à un nombre entier de 0. carbonisation textmult [512]; // données de message, de nbytes de longueur, des données de message lui-même } nbytes : Indique la taille du message ne comprend pas la taille de mtype. drapeau : (1) 0, bloqué. (2) IPC_NOWAIT: similaire à un fichier d'E / S non bloquant drapeau d'E / S. (3) Si la file d'attente de messages contient plein (ou le nombre total d'octets égal au nombre total de limite de file d'attente de messages du système, ou la limite de file d'attente est égale au système), en utilisant la IPC_NOWAIT spécifié msgsnd immédiatement retourner une erreur EAGAIN. Si 0 est spécifié, le processus :. bloc A jusqu'à ce que l'espace peut accueillir un message à envoyer. B. file d'attente ou supprimer du système ;. C ou capturer un signal et renvoie le gestionnaire de signaux. |
fonction |
Envoyer un message |
La valeur de retour |
0 renvoie avec succès, une erreur -1 |
remarque |
Dans Linux, la longueur maximale du message est de 4056 octets, y compris MTYPE, qui occupe 4 octets. |
(6) recevant un message
En-tête |
#include <sys / msg.h> |
fonction |
int msgrcv (int msgqid, void * ptr, size_t nbytes, drapeau d'int); |
paramètres |
le msqid : Message Queue ID PTR : points au tampon pour stocker des messages nbytes : message Taille de la mémoire tampon, la taille ne comprend pas le mtype. calculé: nbytes = sizeof (struct mymesg) - sizeof (long); type:消息类型 (1)type == 0:获取消息队列中的第一个消息 (2)type > 0: 获取消息队列中类型为type的第一个消息 (3)type < 0: 获取消息队列中小于或等于type绝对值的消息(类型最小的) flag:0或IPC_NOWAIT |
功能 |
接收消息 |
返回值 |
成功返回消息的数据部分长度,出错返回-1 |
【编程实验】消息队列
//msq_snd.c //发送进程(要单独编译成一个可执行文件)
#include <stdio.h> #include <stdlib.h> #include <sys/msg.h> //消息结构体 typedef struct{ long type; //消息类型 int start; //消息数据本身(包括start和end) int end; }MSG; /*往消息队列中发送消息*/ int main(int argc, char* argv[]) { //从命令行中转入消息的key if(argc < 2){ printf("usage: %s key\n", argv[0]); exit(1); } key_t key = atoi(argv[1]);//key由用户指定,如10 //key_t key = IPC_PRIVATE; //key由系统指定 //key_t key = ftok(argv[0], 0);//要据文件名和第2个参数生成key printf("key: %d\n", key); //创建或获取消息队列 int msq_id; //IPC_CREAT | IPC_EXCL:不存在则创建,存在时返回错误!(保证对象总是新的) //而不是打开己有的对象 if((msq_id = msgget(key, IPC_CREAT | IPC_EXCL | 0777)) < 0){ perror("msgget error"); } printf("msq id: %d\n", msq_id); //定义要发送的消息 MSG mArr[5] ={ {4, 4, 100}, {2, 2, 200}, {1, 1, 100}, {6, 6, 600},//注意两条type都等于6的消息。 {6, 60, 6000} }; //发送消息到消息队列 int i = 0; for(; i<5; i++){ if(msgsnd(msq_id, &mArr[i], sizeof(MSG)-sizeof(long), IPC_NOWAIT) < 0){ perror("msgsnd error"); } } //发送后获得消息队列中消息的总数 struct msqid_ds ds={0}; if(msgctl(msq_id, IPC_STAT, &ds) < 0){ perror("msgctl error"); } printf("msg total: %d\n", ds.msg_qnum); return 0; } /*输出结果: [root@localhost 11.IPC]# bin/msq_snd 10 //其中的key(10)由用户指定 key: 10 msq id: 65536 msg total: 5 [root@localhost 11.IPC]# ipcs -q //查看消息队列 ------ Message Queues -------- //可以看出有5种消息 key msqid owner perms used-bytes messages 0x0000000a 65536 root 777 40 5 [root@localhost 11.IPC]# ipcrm -q 65536 //删除指定的消息队列 [root@localhost 11.IPC]# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages */
//msg_rcv.c //接收进程(要单独编译成一个可执行文件)
#include <sys/msg.h> #include <stdio.h> #include <stdlib.h> typedef struct{ long type; int start; int end; }MSG; int main(int argc, char* argv[]) { if(argc < 3){ printf("usage: %s key type\n", argv[0]); exit(1); } key_t key = atoi(argv[1]); long type = atoi(argv[2]); //获得指定的消息队列 int msq_id; if((msq_id = msgget(key, 0777)) < 0){ perror("msgget error"); } printf("msg id: %d\n", msq_id); MSG m; if(msgrcv(msq_id, &m, sizeof(MSG)-sizeof(long), type, IPC_NOWAIT) < 0){ perror("msgrcv error"); }else{ printf("type: %d start: %d end: %d\n", m.type, m.start, m.end); } return 0; } /*输出结果: [root@localhost 11.IPC]# bin/msq_snd 10 //send进程,先创建消息队列 key: 10 msq id: 262144 msg total: 5 [root@localhost 11.IPC]# bin/msq_rcv 10 1 //receive进程,从key队列中获得type为1的消息 msg id: 262144 type: 1 start: 1 end: 100 [root@localhost 11.IPC]# bin/msq_rcv 10 2 //获取type为2的消息 msg id: 262144 type: 2 start: 2 end: 200 [root@localhost 11.IPC]# bin/msq_rcv 10 3 //获取type为3的消息(不存在的消息) msg id: 262144 msgrcv error: No message of desired type //获取type为4的消息 [root@localhost 11.IPC]# bin/msq_rcv 10 4 msg id: 262144 type: 4 start: 4 end: 100 [root@localhost 11.IPC]# bin/msq_rcv 10 6 //获取类型为6的第1条消息(先进先出) msg id: 262144 type: 6 start: 6 end: 600 [root@localhost 11.IPC]# bin/msq_rcv 10 6 //获取类型为6的第2条消息 msg id: 262144 type: 6 start: 60 end: 6000 [root@localhost 11.IPC]# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x0000000a 262144 root 777 0 0 [root@localhost 11.IPC]# ipcrm -q 262144 [root@localhost 11.IPC]# ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages */