消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块中,都包含了一种数据类型。我们在消息队列中获取消息时,可以指定它的类型进行获取。
每个消息中都有一个结构体struct mess{};它里面有一个长整型类型,在里面你可以定义自己想要的数据。
消息队列中有四种方法:msgget创建消息 msgsnd添加消息 msgrcv获取消息 msgctl修改消息,原型如下:
*int msgget(key_t ket,int msgflg);
int msgsnd(int msgid,const void msg_ptr,sixe_t msg_sz,int msgflg);
int msgrcv(int msgid,void msg_ptr,size_t msg_sz,lonf int msgtype,int msgflg);
int msgctl(int msgid,int cmd,struct msqid_ds buf);
接下来用过两段代码实现消息的发送和获取:
写入消息:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h> //创建消息队列所需要的头文件
#include <assert.h>
struct mess {
long int type; //定义结构体中的长整型
char buff[128]; //用户自定义数据
};
int main(int argc,char* argv[])
{
int msgtype = 1; //默认消息类型为1号类型
if (argc == 2) //如果参数个数为2时
{
sscanf(argv[1], "%d", &msgtype); //从键盘输入第二个参数(消息队列类型)
}
int msgid = msgget((key_t)1234, IPC_CREAT | 0600); //创建一个消息队列,权限为0600(只有用户人员本身有读写操作)
assert(msgid != -1); //断言msgid不为-1(如果返回值为-1,创建失败)
struct mess dt; //生成一个结构体变量dt
dt.type = msgtype; //知名dt的类型为用户自定义类型
strcpy(dt.buff, "hello"); //将用户的信息写入到消息中
msgsnd(msgid, (void*)&dt, 128, 0); //将消息添加到消息队列中
printf("type:%d", msgtype); //打印消息的类型
exit(0); //退出程序
}
获取消息:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>
#include <assert.h>
struct mess {
long int type;
char buff[128];
};
int main(int argc,char* argv[])
{
int msgtype = 0; //消息队列的默认值为0(读取时不区分消息的类型)
if (argc == 2)
{
sscanf(argv[1], "%d", &msgtype);
}
int msgid = msgget((key_t)1234, IPC_CREAT | 0600);
assert(msgid != -1);
struct mess dt;
msgrcv(msgid, (void*)&dt, 128, msgtype, 0); //获取消息队列中的信息
printf("type:%d,read:%s\n", st.type, dt.buff); //打印出消息的类型和信息的内容
exit(0);
}
写入不同类型的消息,分别写入了三个一号消息,一个二号消息,一个四号消息,两个七号消息
通过ipcs -q来查看运行的消息队列:
进行获取消息操作,此时我们发现当第三次获取七号类型消息时,阻塞了,这是因为我们只定义了两个七号类型消息,所以在第三次获取时阻塞。
总结:
1.发送消息时,必须指定消息类型,否则会默认为一号消息。如果消息队列放满,则发送消息msgsnd会阻塞
2.获取消息时,必须指定类型,类型为0说明不区分消息类型,如果消息队列空,则msgrcv阻塞