POSIX 消息队列

 

1.消息队列是什么?

(1)消息队列是一种IPC方式。

(2)存放于内核中,借助VFS实现,挂载于/dev/mqeueue下。

(3)采用数据结构:带优先级的队列

 

2.消息队列与管道的比较

(1)管道类似于打电话,消息队列类似于邮件。

(2)管道通信,必须发送方和接收方都打开管道,否则通信失败或无意义。

          如果管道关闭,管道内数据将丢失。

(3)消息队列,发送方和接受方可以不同时读写消息队列,

           如果消息队列结构体关闭,消息队列文件中仍然保存数据。

 

3.POSIX 与 SystemV 消息队列比较

POSIX更新,更简单,功能更强大。

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

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

 

4.api学习

(0)链接POSIX消息队列 使用 -lrt

(1)创建一个消息队列文件

使用API:

       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);
void creat_mq(const char *mq_name)
{
    int oflag;
    mode_t mode;
    mqd_t mqd = -1;

    oflag = O_RDWR | O_CREAT | O_EXCL;
    mode = S_IRUSR | S_IWUSR | S_IRGRP  | S_IROTH ;

    mqd = mq_open(mq_name, oflag, mode, NULL);    // 创建的mq在/dev/mqueue下
    if (mqd == -1) {
        perror("mq_open");
        goto __end;
    }

__end:
    if (!mqd) {
        printf("mq_close");
        mq_close(mqd);
    }
}

(3)删除消息队列文件

使用API

int mq_unlink(const char *name);
void unlink_mq(const char *mq_name)
{
    if (mq_unlink(mq_name) < 0) 
        perror("mq_unlink");
}

(4)设置消息队列属性

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

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

相关属性:

           struct mq_attr {
               long mq_flags;       /* Flags: 0 or O_NONBLOCK */
               long mq_maxmsg;      /* Max. number of messages on queue */
               long mq_msgsize;     /* Max. message size (bytes) */
               long mq_curmsgs;     /* # of messages currently in queue */
           };

(5)收发消息

使用API

      int mq_send(mqd_t mqdes, const char *msg_ptr,
                     size_t msg_len, unsigned int msg_prio);
     ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
                          size_t msg_len, unsigned int *msg_prio);
mqd_t open_mq(const char *name, int oflag)
{
    mqd_t mqd = -1;

    mqd = mq_open(name, O_RDWR);
    if (mqd < 0) 
        perror("mq_open");

    return mqd;
}

int send_mq(mqd_t mqd, const char *buf, int len, int priority)
{
    int n;

    n = mq_send(mqd, buf, len , priority);
    if (n < 0 || n != len) {
        perror("mq_send");
    }

    return n;
}

int recv_mq(mqd_t mqd, char *buf)
{
    int n;
    struct mq_attr attr;

    if (mq_getattr(mqd, &attr) < 0) 
        perror("mq_getattr");
    n = mq_receive(mqd, buf, attr.mq_msgsize, NULL);    // 需要使用 msg_len
    if (n < 0 || n != attr.mq_msgsize) 
        perror("mq_receive");

    return n;
}

void test_send_recv()
{
    const char *mq_file = MQ_FILE;
    char buf[100];
    mqd_t mqd = -1;
    int send_number, recv_number, nbytes, priority;

    if ((mqd = open_mq(mq_file, O_RDWR)) < 0)
        goto __end;
    snprintf(buf, sizeof(buf), "hello world\n");
    send_number = 3;
    priority = 20;
    while (send_number--) 
        nbytes = send_mq(mqd, buf, strlen(buf), priority);

    bzero(buf, sizeof(buf));
    recv_number = 4;                // 默认阻塞读
    while (recv_number--) {        
        recv_mq(mqd, buf);
        printf("recv : %s\n", buf);
    }

__end:
    if (mqd != -1)
        close(mqd);
}

需要注意,接受msg时,使用的msg_len从msg文件中获得,即mqd_attr.mq_msgsize。

 

转载于:https://www.cnblogs.com/yangxinrui/p/11229443.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值