1.消息队列原理
1、2…是消息类型,进程发送消息可以指定消息类型,进程接收消息也指定消息类型,这样在消息队列里识别消息类型就可以知道是不是自己需要接受的消息了。
2.消息队列示例代码
函数介绍:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/*
msgget()创建或者获取一个消息队列
msgget()成功返回消息队列 ID,失败返回-1
msqflg: IPC_CREAT
*/
int msgget(key_t key, int msqflg);
/*
msgsnd()发送一条消息,消息结构为:
struct msgbuf
{
long mtype; // 消息类型, 必须大于 0
char mtext[1]; // 消息数据
};
msgsnd()成功返回 0, 失败返回-1
msqsz: 指定 mtext 中有效数据的长度
msqflg:一般设置为 0 可以设置 IPC_NOWAIT//设置为0的话,消息队列添加满了,发送会阻塞。
*/
int msgsnd( int msqid, const void *msqp, size_t msqsz, int msqflg);
/*
msgrcv()接收一条消息
msgrcv()成功返回 mtext 中接收到的数据长度, 失败返回-1
msqtyp: 指定接收的消息类型,类型可以为 0
msqflg: 一般设置为 0 可以设置 IPC_NOWAIT//设置为0,消息队列为空或者没有这类数据的话,会阻塞。
*/
ssize_t msgrcv( int msqid, void *msgp, size_t msqsz, long msqtyp, int msqflg);
/*
msgctl()控制消息队列
msgctl()成功返回 0,失败返回-1
cmd: IPC_RMID
*/
int msgctl( int msqid, int cmd, struct msqid_ds *buf);
示例代码:wr.c进程随机发送消息类型为1、2的消息,进程 rd1.c 读取消息类型为1消息,进程rd2.c读取消息类型为 2的消息。wr.c退出的话,会先发送一条消息类型为1的数据“end”,再发送一条消息类型为 2的数据“end”,rd1和rd2分别读取,并退出,rd2.c程序里销毁消息队列 。
wr.c代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/msg.h>
#include<assert.h>
typedef struct msgdata
{
long mtype;
char mtest[128];
}MsgData;
int main()
{
int msgid = msgget((key_t)1234,IPC_CREAT|0664);
assert(msgid != -1);
MsgData data;
memset(&data,0,sizeof(data));
char buff[128] = {0};
while(1)
{
printf("input:\n");
fgets(buff,128,stdin);
buff[strlen(buff)-1] = '\0';
strcpy(data.mtest,buff);
if(strncmp(buff,"end",3) == 0)
{
data.mtype = 1;
msgsnd(msgid, &data, 128,0);
data.mtype = 2;
msgsnd(msgid,&data,128,0);
break;
}
data.mtype = rand()%2+1;
msgsnd(msgid, &data, 128, 0);
}
exit(0);
}
rd1.c代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/msg.h>
typedef struct msgdata
{
long mtype;
char mtext[128];
}MsgData;
int main()
{
int msgid = msgget((key_t)1234,IPC_CREAT|0664);
assert(msgid != -1);
MsgData data;
memset(&data,0,sizeof(data));
while(1)
{
msgrcv(msgid,&data,128,1,0);
if(strncmp(data.mtext,"end",3) == 0)
{
break;
}
printf("data.typy:%d\n",data.mtype);
printf("data.mtext:%s\n",data.mtext);
}
exit(0);
}
rd2.c代码:
include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/msg.h>
typedef struct msgdata
{
long mtype;
char mtext[128];
}MsgData;
int main()
{
int msgid = msgget((key_t)1234,IPC_CREAT|0664);
assert(msgid != -1);
MsgData data;
memset(&data,0,sizeof(data));
while(1)
{
msgrcv(msgid,&data,128,2,0);
if(strncmp(data.mtext,"end",3) == 0)
{
break;
}
printf("data.typy:%d\n",data.mtype);
printf("data.mtext:%s\n",data.mtext);
}
msgctl(msgid,IPC_RMID,NULL);
exit(0);
}
运行wr.c和rd1.c、rd2.c程序。
wr.c程序发送以下图中消息:
rd1.c程序运行结果:
rd2.c程序运行结果:
在这里,rd2.c里面对消息队列进行了销毁。
如果没在代码里操作销毁消息队列,可以 用命令ipcrm -q + msqid进行销毁。