进程间的通讯—消息队列

消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
特点:

  • I.是消息的链表。具有特定的格式,存放在内存当中,由消息队列标识符标识。
  • II.消息队列允许一个或者多个进程向他写入与读取消息。
  • III.消息队列可实现消息的随机查询,不一定要以先进先出的顺序读取,也可以按照类型进行读取。

相关函数:

msgget(): 用来创建或访问一个消息队列;
		msgsnd(): 用来把消息添加到消息队列中;
		msgrcv(): 从一个消息队列中获取消息;
		msgctl(): 作用与共享内存的控制函数相似;

我们借用一下别人的图来学习一下:

android 消息队列 msmq_#include

什么是消息对列?
——就是一个数据结构,是一个队列。主要是用来实现消息传递。(可以理解为一个链式结构)

什么是消息缓存区?
——如上图,那些绿块块分别是一个一个的消息缓存区。用来存放通道号,和你写入通道中的数据。

struct msgbuf{
	long channel;  //通道号,必须大于0(系统内部其实将它定义为 mtype ——把它视为一个类型)
	char mtext[100];//消息内容(100是自定义的值,你可以任意更改)
	}:

什么是通道?
——通道号就相当于一个分类,并不真实存在。channel 值相同的属于同一通道,系统可以根据通道号来选择对应的消息队列。

对于消息的通道号,程序是有要求的

读端:

channel=0,——返回队列的第一个消息
channel>0,——返回队列中该通道号的第一个消息(相同的通道号归为一类,一个通道里可以放很多相同的通道号)
channel<0,——返回队列中你输入通道号的绝对值,所对应的通道号(若有多个相同的通道号,默认存放最小消息内容的通道号)

写端:

channel=0,——非法(报错)
channel<0,——非法(报错)
channel>0,——可以,继续写入消息内容

消息队列操作:

查看消息队列:

查看消息队列:ipcs -q
删除消息队列:ipcrm -q msgid(id)

头文件:

#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>

写端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/msg.h>

typedef struct msgdata
{
	long mtype;
	char mtext[128];
}Mmsg
int main()
{
	int msgid = msgget((key_t)1234, 0664 | IPC_CREAT);
	assert(msgid != -1);

	MsgData  data;
	memset(&data, 0, sizeof(data));
	data.mtype = 100;
	strcpy(data.mtext, "hello");

	msgsnd(msgid,  &data, strlen(data.mtext), 0);
	exit(0);
}

读端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/msg.h>

typedef struct msgdata
{
	long mtype;
	char mtext[128];
}MsgData;

int main()
{
	int msgid = msgget((key_t)1234, 0664 | IPC_CREAT);
	assert(msgid != -1);

	MsgData  data;
	memset(&data, 0, sizeof(data));

	msgrcv(msgid, &data, 127, 100, 0);
	printf("data.type: %d\n", data.mtype);
	printf("data.text: %s\n", data.mtext);
	
	msgctl(msgid, IPC_RMID, NULL);
	exit(0);
}

android 消息队列 msmq_缓存_02


补充:

android 消息队列 msmq_linux_03