linux消息队列
相关函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
创建消息队列
int msgget(key_t key, int msgflg);
创建或者打开一个消息队列,成功返回消息队列的句柄,失败返回-1
需要提供给函数key(键值)和msgflag操作类型。
所有使用这个消息队列的进程需要使用相同的键值(一个整形数字),保证打开的是同一个消息队列。
操作类型参数的范围:
/* Mode bits for `msgget', `semget', and `shmget'. */
#define IPC_CREAT 01000 /* Create key if key does not exist. */
#define IPC_EXCL 02000 /* Fail if key exists. */
#define IPC_NOWAIT 04000 /* Return error on wait. */
向消息队列中发送消息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//成功返回0,失败返回-1
参数:
msgid 消息队列的句柄,
msgp 要发送的消息结构体指针,
msgsz 发送的消息大小(不包括消息类型),
msgflag 操作类型
解释:
当消息队列中空间被占满时,msgsnd会被阻塞住。但可以将msgflag设置为IPC_NOWAIT,当消息队列满时,会立即返回错误。
从消息队列中接收消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
//成功返回接收到的长度,失败返回-1
参数:
msgid 消息队列的句柄
msgp 接收消息存放位置
msgsz 接收的消息大小
msgtype 消息类型
msgflag 操作类型
参数解释:
msgtype=0 接收消息队列中的第一条消息
msgtype>0 接收消息队列中消息类型等于msgtype的第一条消息
msgtype<0 接收消息队列中类型值小于msgtype绝对值的第一条消息
接收的msgflag操作类型参数,一般设置为0,可以让队列中没有消息时,接收一直阻塞。
消息队列的控制
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
msgid 消息队列句柄
cmd 命令,一般使用IPC_RMID删除消息队列
buf 一般为NULL
消息结构体
结构体可以自己定义,但是最前的成员必须是一个long型数据,表示消息类型。
代码
send.c
#define MSGKEY 1001
#define MSG_TYPE 1
struct msgbuf
{
long mtype; /* message type, must be > 0 */
double Lat;
double Lon;
double Hgt;
};
int main()
{
int msgid;
int ret;
struct msgbuf mbuf;
msgid = msgget(MSGKEY, 0); //打开消息队列
if (-1 == msgid)
{
perror("msgget");
exit(1);
}
{
for(unsigned int i=0;i<10;i++)
{
mbuf.Lat += 10.11;
mbuf.Hgt += 100.0;
mbuf.mtype = MSG_TYPE;
ret = msgsnd(msgid, &mbuf, sizeof(mbuf)-sizeof(mbuf.mtype), 0);
if (-1 == ret)
{
perror("msgsnd");
exit(1);
}
sleep(1);
}
}
sleep(1);
msgctl(msgid, IPC_RMID, NULL);//销毁消息队列
return 0;
}
recv.c
#define MSGKEY 1001
#define MSG_TYPE 1
struct msgbuf
{
long mtype; /* message type, must be > 0 */
double Lat;
double Lon;
double Hgt;
};
int main()
{
int msgid;
int ret;
struct msgbuf mbuf;
msgid = msgget(MSGKEY, IPC_CREAT | IPC_EXCL); //打开消息队列,如果已经存在则报错
if (-1 == msgid)
{
perror("msgget");
exit(1);
}
while (1)
{
memset(&mbuf, 0, sizeof(mbuf));
ret = msgrcv(msgid, &mbuf, sizeof(mbuf)-sizeof(mbuf.mtype), MSG_TYPE,0);
if (-1 == ret)
{
perror("msgrcv");
exit(1);
}
printf("queue recv Lat=%lf,Lon=%lf,Hgt=%lf\n",mbuf.Lat, mbuf.Lon, mbuf.Hgt);
}
return 0;
}