3. Message Queuing
3.1 System V IPC
(1) System V IPC Overview
The basic inter-process communication device presence signal mechanism, and named pipes, etc. ①Unix pipe system.
②System V introduces a communication mechanism between three high-level processes : the message queue and share the shared semaphore .
③IPC object (message queues, semaphores, and shared memory) is present in the kernel rather than the file system , the controlled release by the user (the user lifecycle management object ipc), unlike the release conduit controlled by the kernel.
④IPC object referenced by identifying and accessing all IPC objects in kernel space has a unique identification ID , in the user space of the unique identification of the called Key .
⑤Linux IPC inherited from System V IPC
Access (2) System V IPC objects
①IPC object is a global object: Available ipcs, picrm commands to view or delete .
② Each IPC objects created by the get function: msgget, shmget, semget. Keyword key must be specified when invoking the get function.
Permissions and owner of the structure (3) IPC objects
3.2 Message Queuing
(1) Introduction message queue
① message queue is a linked list of kernel ;
② The user process will transfer data to the kernel, the kernel to add back in as a user ID, group ID, the ID read process and priority related information and encapsulated into a data message packet called.
③ allows one or more processes to write messages in the message queue and read the message, but the message can only be a process of reading, reading is automatically deleted after completion.
④ message queue has a FIFO certain characteristics , the order may be sent to the message queue, several different ways can be read from the queue. Each IPC message queue a unique identification ID expressed by the kernel .
⑤ implement the message queue comprises a queue creation and opening, send a message, read a message and a control message queue four operations.
(2) the structure of the message queue (the msqid_ds)
(3) open and create a message queue
head File |
#include <sys/msg.h> |
function |
int msgget(key_t key, int flag); |
parameter |
key: the message queue specified user key Flag : IPC_CREAT, and other combinations of privileges IPC_EXCL |
Features |
Open or create a message queue |
return value |
Successful return kernel message queue identifier ID, Error -1 |
Remark |
① To create a message queue, key can specify the key, it can also be set to IPC_PRIVATE. ② If you open a query, the key can not be zero, must be a non-zero value, otherwise it can not find. |
(4) a control message queue
head File |
#include <sys/msg.h> |
function |
int msgctl(int msgqid, int cmd, struct msqid_ds* buf); |
parameter |
msgqid : Message Queue ID buf : a pointer message queue attributes cmd: (1) IPC_STAT: Get message queue attributes, taking msqid_ds structure this queue, and store it in buf specified structure. (2) IPC_SET: set properties, according to the value of buf pointed structure, provided the queue associated with this field structure. (3) IPC_RMID: delete a queue, the message queue and delete all the data is still in the queue from the system. |
Features |
A control message queue |
return value |
0 returns successfully, an error -1 |
(5) sends a message
head File |
#include <sys/msg.h> |
function |
int msgsnd(int msgqid, const void* ptr, size_t nbytes, int flag); |
parameter |
the msqid : Message Queue ID ptr : user-defined structure, but the first members must be mtype. struct mymesg{ long mtype; // positive message type, message type, and can only be an integer greater than 0. char mtext [512]; // message data, of length nbytes, message data itself } nbytes : Specifies the size of the message does not include the size of mtype. flag: (1) 0, blocked. (2) IPC_NOWAIT: similar to a file I / O non-blocking I / O flag. (3) If the message queue has full (or the total number of bytes equal to the total number of system message queue limit, or queue limit is equal to the system), using the specified IPC_NOWAIT msgsnd immediately return an error EAGAIN. If 0 is specified, then the process:. A block until space can accommodate a message to be sent. B. queue or delete from the system;. C or capture a signal and returns the signal handler. |
Features |
send messages |
return value |
0 returns successfully, an error -1 |
Remark |
In linux, the maximum message length is 4056 bytes, including MTYPE, which occupies 4 bytes. |
(6) receiving a message
head File |
#include <sys/msg.h> |
function |
int msgrcv(int msgqid, void* ptr, size_t nbytes, int flag); |
parameter |
the msqid : Message Queue ID ptr : points to the buffer to store messages nbytes : message buffer size, the size does not include the mtype. Calculation: 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 */