消息队列是进程间通信的方式之一,从名字上来说,消息队列与队列有关系的,消息的列表,以队列的形式来存储这个列表,所有进程都可以访问这个队列列表。多个进程可以对这个 队列进行添加、删除消息。
消息队列是根据消息类型进行发送/
接收,也就是标号,一个主写,另外的进程去查看这个队列,看队列里面是否有自己需要查找的标号。
消息队列的使用需要完成以下步骤:
1. 创建
/
打开消息队列
2. 读取消息、添加消息
3. 删除关闭消息队列
下面来介绍一下消息队列相关函数:
1、创建打开消息队列 int msgget(key_t key, int msgflg);
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg)
参数1:消息队列在内核中的key值,类似于编号
参数2:权限,访问权限 IPC_CREAT 创建
返回值:
成功:返回创建打开消息队列的id号
失败:-1,设置错误码
2、往消息队列中发送信息和获取信息 int msgsnd(); int msgrcv();
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
//发送信息
int msgsnd(int msqid, const void *msgp,size_t msgst,int msgflg);
参数1:要操作的消息队列id,往里面发送信息
参数2:指针,这是一个结构体,里面有要发送的地址以及内容
struct msg
{
long type; //存地址
xxxx data; //内容
}
参数3:消息队列的大小
参数4:选项 IPC_NOWAIT:调用函数开始发送就立即结束 0:阻塞,等待发送完毕
返回值:
成功:返回0
失败:-1,设置错误码
//接收信息
int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
参数1、2、3、5和发送的一样
参数4:也就是取消息队列里面那一个标号 0:任何类型 >0(写标号):指定类型
3、控制消息队列 int msgctl();
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msgid, int cmd, struct msqid_ds *buf)
参数1:需要控制的消息队列的id
参数2:命令
IPC_STAT:获取消息队列信息,将信息存储在第三个参数地址当中
IPC_SET:设置消息队列,将第三个参数的地址的消息队列内容,设置到内核消息队列当中
IPC_RMID:删除消息队列
参数3:结构体指针地址
设置:地址就表示,把这个指针地址对应空间的消息信息写入到内核
获取:地址就表示,把内核消息队列信息存储到这个地址
4、计算出Key的值
key_t ftok(const char *pathname, int proj_id);
参数:
参数1:const char *pathname:文件路径
参数2:int proj_id:
了解了如何创建、发送、接收等消息队列函数过后,再看下面的例程,疏通一下这些知识,达到更深的理解。
下面这个例程是往消息队列中写入消息
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
struct msg
{
long type;
char buf[20];
}
int main()
{
key_t key = ftok("/home",20);
int msgid = msgget(key,0644 | IPC_CREAT);
while(1)
{
struct msg data; //结构体从命名
scanf("%ld\n",&(data.type)); //存标号,到时候来取
if(data.type <0 ) //存的标号错误,标号必须大于0
{
break;
}
fgets(data.buf,20,stdin); //将内容存储到消息队列
msgsnd(msgid,&data,sizeof(struct msg)-sizeof(long),0)//将data数据以阻塞等待形式发送sizeof(struct msg)-sizeof(long)大小到消息队列中。
}
msgctl(msgid,IPC_RMID,NULL); //删除消息队列
}
然后下面两个例程分别是读消息队列的两个不同的标号
这是读取标号为3的内容
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
struct msg
{
long type;
char buf[20];
};
int main()
{
key_t key = ftok("/home",20);
int msgid;
msgid = msgget(key,0644 | IPC_CREAT);
while(1)
{
struct msg data;
msgrcv(msgid,&data,sizeof(struct msg)-sizeof(long),3,0);//读标号3的内容
printf("type is %d\n",data.type);
printf("msg is %s\n",data.buf);
}
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
这是读取标号10内容的程序,其实和3一样,只是读取标号修改了一下
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
struct msg
{
long type;
char buf[20];
};
int main()
{
key_t key = ftok("/home",20);
int msgid;
msgid = msgget(key,0644 | IPC_CREAT);
while(1)
{
struct msg data;
msgrcv(msgid,&data,sizeof(struct msg)-sizeof(long),10,0);//读标号10的内容
printf("type is %d\n",data.type);
printf("msg is %s\n",data.buf);
}
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
做完这些之后,用Ubuntu进行编译,注意在使用的时候,需要先运行写的程序,在运行读的程序。这就是进程间通信的消息队列,可以做到给谁发,谁接收。