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