消息队列是一种临时存储消息的队列, 完成进程间数据传递, 优先级队列。
与信号量对比: 都以内核对象来确保多进程访问同一个消息队列, 信号量进行进程同步控制, 消息队列发送实际数据。
与管道对比: 管道发送的数据没有类型, 读取数据端无差别从管道中按照数据的前后顺序读取数据;消息队列数据有类型,读端可以根据数据类型读取特定数据。管道是一个文件;消息队列是一个数据结构(类似于链表)。管道文件是存放在磁盘上的,访问速度慢,关机也会存在;消息队列是存在于内核中的内存,访问速度快,关机就没了。无名管道是跟随进程的,消息队列是跟随内核的,也就是说进程结束之后,无名管道就死了,但是消息队列还会存在。管道是数据流式存取,消息队列是数据块式存取。
消息队列的创建或获取
函数原型: int msgget(key_t key, int msgflg)
参数解析 :key是一个标识数据结构唯一的key键值,可以IPC_PRIVATE让内核自动给,也可以自己调用ftok函数绑定一个。
msgflg是创建消息队列的参数,有IPC_CREAT 和 IPC_EXCL 。单独使用IPC_CREAT,如果该消息队列已经存在,则打开该队列并返回,如果不存在,就新建一个返回。
成功返回标志消息队列的唯一的一个int,失败返回-1。
消息队列的发送
函数原型:int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)
参数解析 :msgid是消息队列号。
msgp是一个结构体的指针,这个结构体叫做msgbuf,这个是传输数据的数据块。
msgsz是传输的消息长度。
msgflg是传送方式的参数,没有可以设置为0。
消息队列的获取
函数原型:int msgrcv(int msgid,const void *msgp,size_t msgsz,long msgtyp,int msgflg)
参数解析:msgid是消息队列号。
msgp是一个结构体的指针,这个结构体叫做msgbuf,这个是传输数据的数据块。
msgsz是传输的消息长度。
msgtyp是用来表示当前进程拿数据的时候,只拿(msgbuf对象中的mtype)和传入的msgtyp一样的数据块(msgbuf对象)。
msgflg是传送方式的参数,没有可以设置为0。
成功返回长度,失败返回-1。
消息队列的销毁
函数原型: int msgctl(int msgid ,int cmd ,struct msgid_ds *buf)
参数解析:msgid是创建好的标识msg的int变量
cmd设置为IPC_RMID。
*buf设置为0。
进程B接收并打印进程A的数据
A
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
struct msgbuff
{
long type;
char data[128];
};
void main()
{
int msgid = msgget((key_t)1234, IPC_CREAT | 0664);
assert(msgid != -1);
struct msgbuff buff;
buff.type = 1000;
strcpy(buff.data, "hello");
msgsnd(msgid, &buff, strlen(buff.data), 0);
buff.type = 2000;
strcpy(buff.data, "world");
msgsnd(msgid, &buff, strlen(buff.data), 0);
}
B
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
struct msgbuff
{
long type;
char data[128];
};
void main()
{
int msgid = msgget((key_t)1234, IPC_CREAT | 0664);
assert(msgid != -1);
struct msgbuff buff;
memset(&buff, 0, sizeof(buff));
msgrcv(msgid, &buff, 127, 1000, 0);
printf("%s\n", buff.data);
}