POSIX 消息队列

匿名 (未验证) 提交于 2019-12-02 23:49:02

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。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!