进程间的通讯—消息队列
消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
特点:
- I.是消息的链表。具有特定的格式,存放在内存当中,由消息队列标识符标识。
- II.消息队列允许一个或者多个进程向他写入与读取消息。
- III.消息队列可实现消息的随机查询,不一定要以先进先出的顺序读取,也可以按照类型进行读取。
相关函数:
msgget(): 用来创建或访问一个消息队列;
msgsnd(): 用来把消息添加到消息队列中;
msgrcv(): 从一个消息队列中获取消息;
msgctl(): 作用与共享内存的控制函数相似;
我们借用一下别人的图来学习一下:
什么是消息对列?
——就是一个数据结构,是一个队列。主要是用来实现消息传递。(可以理解为一个链式结构)
什么是消息缓存区?
——如上图,那些绿块块分别是一个一个的消息缓存区。用来存放通道号,和你写入通道中的数据。
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);
}
补充: