一 消息队列通信方式的优点
在unix早期进程通信方式中,信号只能传输有限的数据,管道只能传输无格式的消息流。而消息队列的通信方式则克服了这前两种通信方式的缺点。
二 消息队列的定义
消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式。进程可以向消息队列中按照一定规则添加新的消息,另一个进程则可以从消息队列中读走消息。
三 消息队列的类型
目前主要有两种类型的消息队列,POSIX消息队列以及系统V消息队列。系统V消息队列目前被大量使用。
系统V消息队列是随内核持续的,只有在内核重启或者人工删除时,该消息队列才会被删除。
消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值。
四 消息队列通信的基本步骤
1. 使用ftok函数获得文件名对应的键值;
2. 使用msgget获得与键值项对应的消息队列描述字;
3. 使用msgsnd函数向消息队列中发送消息;
4. 使用msgrcv函数从消息队列中读取数据。
注:消息队列的数据读取和管道内数据读取有一个共同点,那就是数据被读走之后,该消息队列中就不再存在该消息。
五 实例
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>
#include<string.h>
struct msg_buf
{
int m_type;
char data[255];
};
int main(int args, char *argv[])
{
key_t key;
int msgid;
int ret;
struct msg_buf msgbuf;
key = ftok("/tmp/msg",'a');
printf("key is %x\n",key);
msgid = msgget(key,IPC_CREAT|0666);
if(msgid == -1)
{
printf("Creat error!\n");
exit(1);
}
msgbuf.m_type = getpid();
strcpy(msgbuf.data,"Test Duan");
ret = msgsnd(msgid, &msgbuf, sizeof(msgbuf.data),IPC_NOWAIT);
if(ret == -1)
{
printf("Msg send error!\n");
exit(1);
}
memset(&msgbuf,0,sizeof(msgbuf));
ret = msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);
if(ret == -1)
{
printf("Msg get error!\n");
exit(1);
}
printf("recv msg is %s\n",msgbuf.data);
}
运行结果:
key is ffffffff
recv msg is Test Duan