消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。下面是两个测试模块
接收模块
msgreceive.c 的代码如下
/*============================================================================= # FileName: msgreceive.c # Desc: receice message from message queue # Author: Licaibiao # Version: # LastChange: 2017-01-20 # History: =============================================================================*/ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> struct msg_st { long int msg_type; char text[128]; }; int main() { int running = 1; int msgid = -1; int len = 0; long int msgtype = 5; struct msg_st data; msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(-1 == msgid ) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } while(running) { memset(&data.text, 0, 128); len = msgrcv(msgid, (void*)&data, 128, msgtype, 0); if(-1 == len) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("You wrote: %s\n",data.text); if(0 == strncmp(data.text, "end", 3)) running = 0; } //remove message queue if(-1 == msgctl(msgid, IPC_RMID, 0)) { fprintf(stderr, "msgctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
发送模块
/*============================================================================= # FileName: msgsend.c # Desc: send data to message queue # Author: Licaibiao # Version: # LastChange: 2017-01-20 # History: =============================================================================*/ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/msg.h> #include <errno.h> #define MAX_TEXT 512 struct msg_st { long int msg_type; char text[MAX_TEXT]; }; int main() { int running = 1; struct msg_st data; char buffer[BUFSIZ]; int msgid = -1; int len; msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } while(running) { printf("Enter data : "); fgets(buffer, BUFSIZ, stdin); data.msg_type = 5; strcpy(data.text, buffer); len = strlen(data.text); if(msgsnd(msgid, (void*)&data, len-1, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } if(strncmp(buffer, "end", 3) == 0) running = 0; usleep(100000); } exit(EXIT_SUCCESS); }
编译执行结果如下:
扫描二维码关注公众号,回复:
55893 查看本文章
root@ubuntu:/home/test/msg_test# gcc msgsend.c -o send root@ubuntu:/home/test/msg_test# gcc msgreceive.c -o recv root@ubuntu:/home/test/msg_test# ./recv & [1] 106594 root@ubuntu:/home/ysj000/quanzhiSDK/F25_test/test/msg_test# ./send Enter data : hello You wrote: hello Enter data : test You wrote: test Enter data : hello world You wrote: hello world Enter data : end You wrote: end [1]+ Done ./recv root@ubuntu:/home/test/msg_test#这里需要注意,在接收端消息队列类型中的msg_type,如果设置为0,则表示接收所有的消息。如果非零,则只接收与发送端类型一样的消息。比如接收端设置为3,那么接收端只接收发送端msg_type为3进程发送过来的消息。
与命名管道相比,消息队列的优势在于:
1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。
2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。
3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。