消息队列操作流程大概可以分为以下几个步骤:
1、使用ftok()函数创建消息队列的key值:
//from /usr/include/sys/ipc.h
key_t ftok(const char* path,int id);
第1个参数为任意一个文件名,第2个参数为任意id值。
2、使用函数msgget()创建消息队列ID值:
//from /usr/include/sys/msg.h
int msgget(key_t key,int msgflag);
函数第1个参数为ftok()返回的键值,第2个参数为该消息队列的权限,且msgflag的高位包含以下属性项:
//from /usr/include/bit/ipc.h
#define IPC_CREAT 00001000 //如果key值不存在则创建
#define IPC_EXCL 00002000 //如果key存在,则返回失败
#define IPC_NOWAIT 00004000 //如果需要等待时,直接返回错误
3、使用msgctl()函数设置或获取消息队列属性:
//from /usr/include/sys/msg.h
int msgctl(int msgid,int cmd,struct msqid_ds* buf);
函数第1个参数为msgget()返回的消息队列标识符,第2个参数cmd为执行的控制操作,包括以下选项:
//from /usr/include/linux/ipc.h
#define IPC_RMID 0 // 立即删除消息队列
#define IPC_SET 1 // 设置buf中的消息队列属性
#define IPC_STAT 2 // 获取消息队列的属性并保存在buf中
#define IPC_INFO 3 // 获取限制信息
4、使用msgsnd()函数发送消息:
//from /usr/include/sys/msg.h
int msgsnd(int msgid,void* msg,size_t size,int msgflag);
函数第1个参数为消息队列标识符,第2个参数为用户定义的缓冲区,使用以下结构:
//from /usr/include/sys/msg.h
struct msgbuf
{
long mtype; //消息类型
char mtext[1]; //消息内容,可重新定义
};
第3个参数为接收消息的大小,第4个参数指定消息达到系统界限时,要采取的操作,一般取IPC_NOWAIT即如果需要等待,则函数立即返回错误。若设置为0,则表示函数将会一直阻塞。
5、使用msgrcv()函数接收消息:
//from /usr/include/sys/msg.h
int msgrcv(int msgid,void* msg,size_t size,,long mtype,int msgflag);
函数参数同msgsnd()一样,只是多了一个mtype,表示要接收的消息队列类型。
以下是消息队列测试代码,起动两个进程,一个不断从终端读取数据并发送出去,另一个进程不断读取消息队列内容,并打印出来,方式均为非阻塞
msg_send.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct msg
{
int mtype;
char mtext[1024];
}MSG;
int main()
{
MSG msg;
key_t key;
int msgid = 0;
char sendbuf[1024];
struct msqid_ds buf;
memset(&buf,0,sizeof(struct msqid_ds));
memset(sendbuf,0,sizeof(sendbuf));
memset(&msg,0,sizeof(msg));
key = ftok("/tmp",'a');
msgid = msgget(key,0755|IPC_CREAT);
while(1)
{
memset(&msg,0,sizeof(MSG));
gets(msg.mtext);
msg.mtype = 10;
if(msgsnd(msgid,&msg,sizeof(msg),0))
{
printf("msgsnd fail\n");
exit(1);
}
}
return 0;
}
msg_recv.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
typedef struct msg
{
int mtype;
char mtext[1024];
}MSG;
int main()
{
MSG msg;
key_t key;
int msgid = 0;
char sendbuf[1024];
struct msqid_ds buf;
memset(&buf,0,sizeof(struct msqid_ds));
memset(sendbuf,0,sizeof(sendbuf));
key = ftok("/tmp",'a');
msgid = msgget(key,0755|IPC_CREAT);
while(1)
{
memset(&msg,0,sizeof(msg));
msgrcv(msgid,&msg,sizeof(msg),11,0);
printf("mtype=%d,msgrcv = %s\n",msg.mtype,msg.mtext);
}
return 0;
}