进程间通信(IPC) --- 消息队列

       消息队列是消息的链接表,存储在内核中,由消息队列标识符标识。有足够写权限的进程可往队列中放置消息,有足够读权限的进程可从队列中取走消息。POSIX 和 system V 下的消息队列略有不同,主要体现在一下几个方面:

  • 一般来说 POSIX 的接口要比 system V 的简单,但是 system V 的可已移植性更好,几乎所有的 UNIX 系统都支持
  • 对 POSIX 消息队列的读总是返回最高优先级的最早消息,对 system V 消息队列的读则可以返回任意指定优先级的消息
  • 当往一个空队列放置一个消息时,POSIX 消息队列允许产生一个信号或者启动一个线程,system V 消息队列则不提供类似的机制

       这里我们以 POSIX 下的消息队列为例来进行讲解。

消息队列的创建

       消息队列的 mq_open 函数如同操作文件的 open 函数,用于打开或创建一个消息队列,其接口定义如下:

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <mqueue.h>

mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);

       消息队列中的 mode 位同普通文件操作的 mode 位使用是完全一致的。

       调用 fork 之后,子进程也获得了消息队列的描述符,因此子进程同样也可以打开这个消息队列。当子进程调用 exec 之后,由于内核实现中消息队列的描述符带有 O_CLOEXEC 标志位,所以其打开的消息队列会被自动关闭。

       当进程退出时,所有打开的消息队列都会被关闭。

消息队列的关闭和销毁

       mq_close 函数用于消息队列的关闭,这个函数和文件关闭的 close 函数十分相似,其接口定义如下:

#include <mqueue.h>

int mq_close(mqd_t mqdes);

       POSIX 消息队列具有内核持久性,即使打开该消息队列的所有进程都执行了 mq_close,消息队列的引用计数已经变为 0,但只要不显式的调用 mq_unlink 函数,该队列及队列上的消息依然存在。要想销毁队列,必须要调用 mq_unlink 函数,其接口定义如下:

#include <mqueue.h>

int mq_unlink(const char *name);

消息队列的属性

       首先我们来看一下消息队列的结构体是如何定义的:

struct mq_attr {
    long mq_flags;
    long mq_maxmsq;
    long mq_msgsize;
    long mq_curmsgs;
}

       这个结构体定义在 <mqueue.h> 文件中,其中:

  • mq_flags:0 或设置了 O_NONBLOCK
  • mq_maxmsg:消息队列中的最大消息个数
  • mq_msgsize:单条消息允许的最大字节数
  • mq_curmsgs:消息队列当前的消息个数

       如果调用 mq_open 函数创建消息队列时,第四个参数为 NULL,那么将使用默认属性,使用 mq_getattr 函数可查看消息队列的属性,其接口定义如下:

#include <mqueue.h>

int mq_getattr(mqd_t mqdes, struct mq_attr *attr);

       使用 mq_setattr 函数可以修改消息队列的 mq_flags 属性,其接口定义如下:

#include <mqueue.h>

int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);

发送消息

#include <mqueue.h>

int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);

       第三个参数 msg_len 表示消息体的长度,长度为 0 也是合法的,最大不能超过 mq_msgsize。如果消息体太大,则会返回失败,并设置 errno 为 EMSGSIZE。

       第四个参数为消息的优先级,是一个非负的整数,数字越大优先级越高,在 linux 中,优先级的最大上限为32768。

接收消息

#include <mqueue.h>

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);

       对于 POSIX 消息队列来说,最先被取走的总是到达的消息中优先级最高的一个,如果有多个消息优先级相同,那么就取走最先到达的一个。

       第二个参数 msg_ptr 用于存放消息体的内存缓冲区的地址。第三个参数 msg_len 是指向缓冲区的大小(必须大于等于属性值 mq_msgsize 的值,否则返回 EMSGSIZE )。 第四个参数为消息的优先级,如果 msg_prio 不为 NULL,那么接收到的消息优先级会被复制到prio指向的位置,如果第四个参数为 NULL,则表示不关系该消息体的优先级。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值