欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

消息队列

程序员文章站 2022-05-18 10:48:08
...

消息就是数据,队列在数据结构中学到过,其特点是先进先出。在这里消息不仅仅是数据,还包括类型,我们获取消息时有优先级。因为消息有类型,我们获取消息时可以选择优先获取哪种类型的数据。消息队列是一种临时储存消息的队列,完成进程间的数据传递。


与信号量对比:都是以内核对象来确保多进程访问同一个消息队列,信号量进行进程同步控制,消息队列发送实际数据。

与管道对比:管道发送的数据没有类型,读取数据端无差别的从管道中按先后顺序读取数据,消息队列数据有类型,读端根据数据类型读取特定的数据。


接下来就是操作:

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);

}
结果如下:

消息队列