消息队列:提供了一种从一个进程向另一个进程发送一个数据块的方法,而且每个数据块都被认为含有一个类型,接收进程可以独立地接受含有不同类型值得数据块。
消息:数据 & 类型
队列:一种数据结构,先进先出
消息队列:是一种临时存储信息的队列,完成进程间的数据传递,优先级队列
消息队列的特点:
1.与信号量相比:都以内核对象来确保多进程访问同一个消息队列,信号量进行同步控制,消息队列发送实际数据。
2.与管道相比:管道发送的数据没有类型,读取数据端无差别从管道中按照数据的前后顺序读取数据,消息队列数据有类型,读端可以根据数据类型读取特定数据。
消息队列的相关操作:
创建或获取:int msgget((key_t)key, int flag);
key:键值
flag:权限以及控制,由9个权限标志组成。由IPC_CREAT定义的一个特殊位必须和权限标志按位或才能创建一个新的消息队列。
如果消息队列已经存在,则直接获取;如果不存在,则创建。
成功时 msgget 函数返回一个正整数,即队列标识符,失败时返回-1;
发送消息:int msgsnd(int msgid, void *ptr, size_t size, int flag);
msgid:是由 msgget 函数返回的 消息队列标识符
ptr:指向一个结构体:类型+数据
size:数据的大小
成功时这个函数返回 0,失败时返回 -1。如果调用成功,消息队列数据的一份副本将被放到消息队列中。
获取消息:int msgrcv(int msgid, void *ptr, size_t size, long type, int flag);
删除消息队列:int msgctl(int msgid, int cmd, struct msgid_ds *buff);
cmd:是将要采取的动作,它可以取 3 个值:IPC_STAT,IPC_SET,IPC_RMID
migid_ds 的结构体至少包含一下成员:
struct msgid_ds
{
uid_t msg_perm.uid;
uid_t msg_perm.gid;
mode_t msg_perm.mode;
}
成功是它返回 0,失败时返回 -1。
练习:A 进程负责根据用户选择的数据类型(long)发送用户输入的数据(char *),B 进程读取1000类型的数据,C 进程读取2000类型的数据
A进程代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuff
{
long type;
char data[128];
};
void main()
{
int msgid = msgget((key_t)1234, IPC_CREAT|0664);
assert(msgid != -1);
struct msgbuff buffer;
buffer.type = 1000;
strcpy(buffer.data, "hello");
msgsnd(msgid, &buffer, strlen(buffer.data), 0);
buffer.type = 2000;
strcpy(buffer.data,"world");
msgsnd(msgid, &buffer, strlen(buffer.data), 0);
}
B 进程代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
struct msgbuff
{
long type;
char data[128];
};
void main()
{
int msgid = msgget((key_t)1234, IPC_CREAT|0664);
assert(msgid != -1);
struct msgbuff buffer;
memset(&buffer, 0, sizeof(buffer));
msgrcv(msgid, &buffer, 127, 1000, 0);
printf("%s\n", buffer.data);
}
C 进程代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
struct msgbuff
{
long type;
char data[128];
};
void main()
{
int msgid = msgget((key_t)1234, IPC_CREAT|0664);
assert(msgid != -1);
struct msgbuff buffer;
memset(&buffer, 0, sizeof(buffer));
msgrcv(msgid, &buffer, 127, 2000, 0);
printf("%s\n", buffer.data);
}
测试运行结果如下: