消息队列(mqueue)深入理解

消息队列的实现分为两种,一种为System V的消息队列,一种是Posix消息队列;这篇文章将主要围绕Posix消息队列介绍;

消息队列可以认为是一个消息链表,某个进程往一个消息队列中写入消息之前,不需要另外某个进程在该队列上等待消息的达到,这一点与管道和FIFO相反。Posix消息队列与System V消息队列的区别如下:

(1) 对Posix消息队列的读总是返回最高优先级的最早消息,对System V消息队列的读则可以返回任意指定优先级的消息。

(2)当往一个空队列放置一个消息时,Posix消息队列允许产生一个信号或启动一个线程,System V消息队列则不提供类似的机制。

2、消息队列的基本操作

2.1 打开一个消息队列

#include    <mqueue.h>

typedef int mqd_t;

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

返回: 成功时为消息队列描述字,出错时为-1。 

功能: 创建一个新的消息队列或打开一个已存在的消息的队列。

2.2 关闭一个消息队列

#include    <mqueue.h>

int mq_close(mqd_t mqdes);

返回: 成功时为0,出错时为-1。

功能: 关闭已打开的消息队列。

2.3 删除一个消息队列

#include    <mqueue.h>

int mq_unlink(const char *name)

返回: 成功时为0,出错时为-1

功能: 从系统中删除消息队列。

这三个函数操作的代码如下:

#include <mqueue.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    int flag = O_RDWR | O_CREAT | O_EXCL;
    int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    mqd_t mqid = mq_open("/mq_test", flag, mode,NULL);
    if (mqid == -1)
    {
        printf("mqueue create failed!\n");
        return 1;
    }
    else
    {
        printf("mqueue create success!\n");
    }
    mq_close(mqid);  return 0;
}

#include <mqueue.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
    mq_unlink("/mq_test");   
    return 0;
}

注意:编译posix mqueue时,要连接运行时库(runtime library),既-lrt选项,运行结果如下:

消息队列(mqueue)深入理解

关于mqueue更多详细内容可以使用:man mq_overview命令查看,里面有一条需要注意的是,Linux下的Posix消息队列是在vfs中创建的,可以用

mount -t mqueue none /dev/mqueue

将消息队列挂在在/dev/mqueue目录下,便于查看。

2.4 mq_close()和mq_unlink()

mq_close()的功能是关闭消息队列的文件描述符,但消息队列并不从系统中删除,要删除一个消息队列,必须调用mq_unlink();这与文件系统的unlink()机制是一样的。

3、消息队列的属性

#include    <mqueue.h>

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

int mq_setattr(mqd_t mqdes, const struct mq_attr *attr, struct mq_attr *attr);

均返回:成功时为0, 出错时为-1

每个消息队列有四个属性:
struct mq_attr
{
    long mq_flags;       /* message queue flag : 0, O_NONBLOCK */
    long mq_maxmsg;  /* max number of messages allowed on queue*/
    long mq_msgsize;  /* max size of a message (in bytes)*/
    long mq_curmsgs;  /* number of messages currently on queue */
};

4、消息收发

#include    <mqueue.h>

int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio);

返回:成功时为0,出错为-1

ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len, unsigned int *priop);

返回:成功时为消息中的字节数,出错为-1

mqsend代码如下:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char* argv[])
{
    int flag = O_RDWR;
    int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    mqd_t mqid = mq_open("/mq_test",flag,mode,NULL);
    if (mqid == -1)
    {
        printf("open mqueue failed!\n");
        return 1;
    }

char *buf = "hello, i am sender!";
    mq_send(mqid,buf,strlen(buf),20);
    mq_close(mqid);
   
    return 0;
}

mqrecv代码如下:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <sys/types.h>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12866.html