Chapitre 11 Communication inter-processus (2) _ file de messages

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  
 */

复制代码

发布了25 篇原创文章 · 获赞 4 · 访问量 2万+

Je suppose que tu aimes

Origine blog.csdn.net/zhou8400/article/details/97392295
conseillé
Classement