Capítulo 11 Comunicación entre procesos (2) _ cola de mensajes

3.  Message Queuing

3.1 Sistema V IPC

(1) Sistema V IPC general

  El dispositivo de comunicación mecanismo básico entre procesos señal de presencia, y las canalizaciones con nombre, etc. sistema de tuberías ①Unix.

  ②System V introduce un mecanismo de comunicación entre tres procesos de alto nivel : la cola de mensajes y de compartir el semáforo compartido .

  ③IPC objeto (colas de mensajes, semáforos y memoria compartida) está presente en el núcleo en lugar del sistema de archivos , la liberación controlada por el usuario (el ciclo de vida del usuario objeto de gestión ipc), a diferencia del conducto de liberación controlada por el núcleo.

  objeto ④IPC referenciado por identificar y acceder a todos los objetos IPC en el espacio del núcleo tiene una identificación única ID , en el espacio de usuario de la identificación única del llamado Key .

  ⑤Linux IPC heredado de System V IPC

De acceso (2) los objetos del sistema V IPC

  ①IPC objeto es un objeto global: ipcs disponibles, comandos picrm para ver o eliminar .

  ② Cada IPC objetos creados por la función get: msgget, shmget, semget. clave de palabra clave debe especificarse cuando se invoca la función get.

Permisos y propietario de la estructura (3) objetos IPC

3.2  Message Queue Server

cola de mensajes (1) Introducción

  ① cola de mensajes es una lista enlazada de núcleo ;

  ② El proceso de usuario transferirá los datos al núcleo, el núcleo para poner de nuevo en como un ID de usuario, ID de grupo, la ID de proceso y la información relacionada prioridad leer y encapsula en un paquete de mensajes de datos llamado.

  ③ permite que uno o más procesos de escritura a los mensajes en la cola de mensajes y leer el mensaje, pero el mensaje sólo puede haber un proceso de lectura, la lectura se elimina automáticamente después de la finalización.

  ④ cola de mensajes tiene un FIFO ciertas características , el pedido puede ser enviado a la cola de mensajes, de varias maneras diferentes se pueden leer en la cola. Cada mensaje IPC cola un ID único de identificación expresado por el núcleo .

  ⑤ aplicar la cola de mensajes comprende una cola de creación y apertura, enviar un mensaje, leer un mensaje y un mensaje de cola de control cuatro operaciones.

(2) la estructura de la cola de mensajes (los msqid_ds)

(3) abrir y crear una cola de mensajes

encabezamiento

#include <sys / msg.h>

función

int msgget (clave key_t, bandera int);

parámetros

clave:  la clave de usuario cola de mensajes especificada

Bandera : IPC_CREAT, y otras combinaciones de privilegios IPC_EXCL

función

Abrir o crear una cola de mensajes

El valor de retorno

retorno exitoso kernel cola de mensajes identificador ID, Error -1

observación

① Para crear una cola de mensajes, la llave se especifique la clave, también puede ser ajustado a IPC_PRIVATE.

② Si abre una consulta, la clave no puede ser cero, debe ser un valor que no sea cero, de lo contrario no se puede encontrar.

(4) una cola de mensajes de control

encabezamiento

#include <sys / msg.h>

función

int msgctl (int msgqid, int cmd, msqid_ds struct * buf);

parámetros

msgqid : Message Queue ID

buf : Atributos de una cola de mensajes del puntero

cmd :

(1) IPC_STAT: Obtener atributos de cola de mensajes, teniendo msqid_ds estructurar esta cola, y almacenarlo en buf estructura especificada.

(2) IPC_SET: Propiedades de conjunto, de acuerdo con el valor de buf estructura puntiaguda, siempre que la cola asociada con esta estructura de campo.

(3) IPC_RMID: borrar una cola, la cola de mensajes y borrar todos los datos están todavía en la cola del sistema.

función

Una cola de mensajes de control

El valor de retorno

0 devuelve con éxito, un error -1

(5) envía un mensaje de

encabezamiento

#include <sys / msg.h>

función

int msgsnd (int msgqid, const void * ptr, nbytes size_t, int flag);

parámetros

la msqid : Message Queue ID

ptr : user-define estructura, pero los primeros miembros debe ser mtype.

mymesg struct {

  largo mtype; // tipo de mensaje positivo, tipo de mensaje, y sólo puede ser un número entero mayor que 0.

  Char mtext [512]; // datos del mensaje, de nbytes longitud, en sí datos de mensajes

}

nbytes : Especifica el tamaño del mensaje no incluye el tamaño de mtype.

bandera :

(1) 0, bloqueado. (2) IPC_NOWAIT: / bandera similar a un archivo de E / S no bloqueante O.

(3) Si la cola de mensajes tiene plena (o el número total de bytes igual al número total de mensajes del sistema límite de la cola, o límite de la cola es igual a la del sistema), utilizando el IPC_NOWAIT especificado msgsnd inmediatamente devolver un EAGAIN error. Si se especifica 0, entonces el bloque de proceso :. A hasta que el espacio puede acomodar un mensaje a ser enviado. B. cola o borrarlo del sistema ;. C o capturar una señal y devuelve el manejador de la señal.

función

Enviar un mensaje

El valor de retorno

0 devuelve con éxito, un error -1

observación

En Linux, la longitud máxima del mensaje es 4056 bytes, incluyendo MTYPE, que ocupa 4 bytes.

(6) recibir un mensaje

encabezamiento

#include <sys / msg.h>

función

int msgrcv (int msgqid, nula ptr *, nbytes size_t, int flag);

parámetros

la msqid : Message Queue ID

PTR : apunta al buffer para almacenar los mensajes

nbytes : tamaño del búfer de mensajes, el tamaño no incluye el mtype. Calculado:

nbytes = sizeof (mymesg struct) - sizeof (largo);

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万+

Supongo que te gusta

Origin blog.csdn.net/zhou8400/article/details/97392295
Recomendado
Clasificación