消息队列
消息就是数据,队列在数据结构中学到过,其特点是先进先出。在这里消息不仅仅是数据,还包括类型,我们获取消息时有优先级。因为消息有类型,我们获取消息时可以选择优先获取哪种类型的数据。消息队列是一种临时储存消息的队列,完成进程间的数据传递。
与信号量对比:都是以内核对象来确保多进程访问同一个消息队列,信号量进行进程同步控制,消息队列发送实际数据。
与管道对比:管道发送的数据没有类型,读取数据端无差别的从管道中按先后顺序读取数据,消息队列数据有类型,读端根据数据类型读取特定的数据。
接下来就是操作:
1、创建/获取:int msgget(key_t key, int flag);
key就是键值,与其他IPC一样。
flag是权限以及控制。按位或IPC_CREAT,如果存在直接获取;如果不存在则创建。
成功返回消息队列ID,失败返回-1.
2、发送消息:int msgsnd(int msgid,void*ptr,size_t size,int flag);
msgid 就是消息队列ID,指定是哪一个消息队列,通过msgget函数得到。
ptr 指向一个结构体,定义了要发送的数据和类型。
size 数据的大小。
flag 控制当前消息队列满或消息队列达到系统限制时将要发生的事情,如果设置了IPC_NOWAIT标志函数将立刻返回,不发送消息且返回值为-1,如果没有则发送进程将挂起以等待队列中腾出可用空间。
成功返回0,失败返回-1。如果成功,消息数据的一份副本放到消息队列中。
3、获取消息:int msgrcv(int msgid,void*ptr,size_t size,long type,int flag);
msgid 就是消息队列ID,指定是哪一个消息队列,通过msgget函数得到。
ptr 可以理解成一个char*buff,把获取到的数据放到buff中。
size 就是buff的大小。
type 数据类型,就是我们要获取哪种类型的数据。
type==0 返回队列中的第一个消息。
type > 0 返回队列中消息类型为type的第一个消息。
type < 0 返回队列中消息类型值小于或等于type绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
flag 控制当前队列中没有相应类型的消息可以接收时将发生的事,如果设置了IPC_NOWAIT标志函数将立刻返回,返回值为-1,如果没有则发送进程将挂起以等待一条相应类型的消息。
成功时返回放到缓存区的字节数,消息被复制到ptr指定的缓存区,然后删除消息队列中的对应的消息。失败时返回-1。
4、删除消息队列:int msgctl(int msgid, int cmd,struct msgid_ds *buff);
msgid 就是消息队列ID,指定是哪一个消息队列,通过msgget函数得到。
cmd 指定进行什么操作,
IPC_STAT 把msgid_ds结构体中的数据设置为消息队列的当前关联值;
IPC_SET 把消息队列的当前关联值设置成msgid_ds结构体中给出的值;
IPC_RMID 删除消息队列。
成功返回0,失败返回-1。如果删除消息队列时,某个进程正在msgsnd或msgrcv等待,这两个函数将失败。
下面是一个简单的例子
msga.c
#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);
}
msgb.c
#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);
}
结果如下: