目录
1.原理
2.消息队列的系统调用
2.1 msgget
2.2 msgsnd
2.3 msgrcv
2.4 msgctl
3.消息队列的使用——代码演示
4.结论
1.原理
2.消息队列的系统调用
2.1 msgget
用于创建或者获取一个消息队列。成功返回消息队列ID,失败返回-1。
int msgget(key_t key,int msqflg);
msqflg:IPC_CREAT
2.2 msgsnd
用于发送一条消息。成功返回0,失败返回-1。
int msgsnd(int msqid, const void* msqp, size_t msgsz,int msgflg);
msqid:消息队列的id,因为系统中可能有多个消息队列,这id指明往哪个消息队列中添加数据;
msqp:往消息队列中添加的结构体,消息结构为:
struct msgbuf
{
long mtype;//消息类型,必须大于0(或者说>=1,0代表顺位接收),长整型,比如图中的1,2
char mtext[1];//消息数据,用户自己定义,可以是任何类型;这里存放消息数据
};
msqsz:指定mtext中有效数据的长度。注意:仅仅指接收的数据的大小,不包含消息类型的大小;
msqflg:标志位,一般设置为0,可以设置IPC_NOWAIT,比如消息队列满了,是阻塞还是失败返回呢?给0代表消息满了自动阻塞,设置IPC_NOWAIT意思是当整个消息队列满的时候会立即返回(no wait),返回一个失败而已。
2.3 msgrcv
用来接收一条消息,成功返回mtext中接收到的数据长度,失败返回-1。
ssize_t msgrcv(int msqid, void* msgp, size_t msgsz, long msgtyp, int msgflg);
msgp:接收消息的结构体,一般约定好,写入什么,接收什么结构体。
msgsz:接收消息的大小,大于等于发送的消息大小,一般和发送的消息大小一样。
msgtyp:指定接收的消息类型(图中的1和2),类型可以为0,为0表示不区分消息类型,按顺位接收消息。
msgflg:一般设置为0,可以设置为IPC_NOWAIT。设置为IPC_NOWAIT,意思是当整个消息队列空的时候会立即返回(no wait),返回一个失败而已;设置为0,意思是当整个消息队列空的时候会阻塞。
2.4 msgctl
用于控制消息队列,也就是对消息队列做一个控制,可以设置消息队列,也可以移除消息队列;成功返回0,失败返回-1。
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
cmd:IPC_RMID
buf:设置或者获取消息队列需要的一个结构体,如果删除就直接给一个NULL。
注:当创建一个消息队列的时候,只要不移除这个消息队列,它就会一直在,除非重启系统。
或者人为删除:ipcrm -q id
3.消息队列的使用——代码演示
进程a发送一条消息,进程b读取消息。
//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/msg.h>
#include <string.h>
struct mess
{
long type;
char buff[128];
};
int main()
{
int msgid=msgget((key_t)1234,IPC_CREAT|0600);
assert(msgid!=-1);
struct mess dt;
dt.type=1;
strcpy(dt.buff,"hello1");
msgsnd(msgid,&dt,128,0);
exit(0);
}
//b.c
include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/msg.h>
#include <string.h>
struct mess
{
long type;
char buff[128];
};
int main()
{
int msgid=msgget((key_t)1234,IPC_CREAT|0600);
assert(msgid!=-1);
struct mess dt;
msgrcv(msgid,&dt,128,1,0);
printf("read mess:%s\n",dt.buff);
exit(0);
}
运行结果:
4.结论
1)没有0号消息,0表示顺位接收,不管什么类型的消息都接收,因为没有0号消息,只有>=1的消息。
2)可以使用ipcrm删除队列,也可以在程序中删除。
方法一:
查看命令:ipcs -q/-m/-s
删除命令:ipcrm -q/-m/-s id
方法二:
msgctl(msgid,IPC_RMID,NULL);
3)如果设置成IPC_NOWAIT,没有消息不等待
if(msgrcv(msgid,&dt,128,1,IPC_NOWAIT)==-1)
{
printf("no mess\n");
}
else
{
printf("read:%s\n",dt.buff);
}
修改后b.c代码:
//b.c
include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/msg.h>
#include <string.h>
struct mess
{
long type;
char buff[128];
};
int main()
{
int msgid=msgget((key_t)1234,IPC_CREAT|0600);
assert(msgid!=-1);
struct mess dt;
if(msgrcv(msgid,&dt,128,1,IPC_NOWAIT)==-1)
{
printf("no mess\n");
}
else
{
printf("read:%s\n",dt.buff);
}
exit(0);
}
修改后运行结果:
4)消息队列在内存中创建。