POSIX消息队列 发送接收简单子

来源:互联网 发布:mac如何连续选中 编辑:程序博客网 时间:2024/04/30 00:32

Linux的函数库提供有两种消息队列,一种是POSIX消息队列,另一种是SYS V消息队列。这里介绍POSIX消息队列。

涉及到的函数主要有:

  • mq_open() - 创建消息队列
  • mq_close() - 关闭消息队列
  • mq_send() - 往消息队列里发送消息
  • mq_receive() - 从消息队列里接受消息
消息队列实际上是一个文件,因此需要消息队列虚拟文件系统的支持。通常系统启动时,在/dev目录下,会有一个/mqueue目录来暂存所有的消息队列。如果没有这个目录,就需要先挂载。
# mkdir /dev/mqueue# mount -t mqueue none /dev/mqueue

打开和关闭消息队列的操作和打开关闭普通文件的操作几乎一样。而发送接收也和普通文件的读写操作十分相似。
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);
打开操作有两个形式,通常使用第二种形式的打开函数。因为它有更多的可选参数,可以控制文件的打开方式和读写权限。参数中,name是文件的路径,根据mq_overview的man page所说,它的形式必须是/somename(以斜线开头),这里的somename也是最终在/dev/mqueue中可以看见的消息队列的文件名。第二个参数oflag是打开方式,只读、只写、读写等方式,与open的参数相同。第三个是mode是文件的权限(755、777等),也是和open相同的。最后一个参数attr是消息队列的参数。执行成功,返回已打开的消息队列的描述符。

int mq_send(mqd_t mqdes, const char *msg_ptr,                     size_t msg_len, unsigned msg_prio);
mq_send()用于写一条消息到消息队列。第一个参数mqdes是消息队列的描述符,也就是mq_open()函数的返回值。第二个msg_ptr是要发送的消息的指针。第三个msg_len是要发送的消息的长度。第四个msg_prio是消息的优先级,优先级按降序排列,数字越大优先级越高。

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,                          size_t msg_len, unsigned *msg_prio);
mq_receive()用于从消息队列读取一条消息。第一个参数mqdes是消息队列的描述符。第二个msg_ptr是接收消息的缓冲区。第三个msg_len是要接收的消息的长度。第四个msg_prio是消息的优先级。

发送端:
/× server.c */#include <stdio.h>#include <fcntl.h>           /* For O_* constants */#include <sys/stat.h>        /* For mode constants */#include <mqueue.h>#include <string.h>#include <errno.h>#define PATHNAME "/msg_test"#define PRIOLOW 1#define PRIOHIGH 2int main(){mqd_t mqd;char name[24] = "/msg_test";char data[24] = "Hello World!";char data_new[32] = "Hello World, again!";struct mq_attr attr;attr.mq_msgsize = strlen(data);mqd = mq_open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, NULL);if (mqd == -1) {printf("errno: %d\n", errno);perror("open failed!!!: ");return 0;}mq_send(mqd, name, strlen(name), PRIOLOW);mq_send(mqd, data, strlen(data), PRIOHIGH);mq_send(mqd, data_new, strlen(data_new), PRIOHIGH);mq_close(mqd);return 0;}

接收端:
/* client.c */#include <stdio.h>#include <fcntl.h>           /* For O_* constants */#include <sys/stat.h>        /* For mode constants */#include <mqueue.h>#include <string.h>#define PATHNAME "/msg_test"#define PRIO 1int main(){mqd_t mqd;char name[24] = "/msg_test";struct mq_attr attr;char data[32];int prio;int len;mqd = mq_open(name, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, NULL);mq_getattr(mqd, &attr);if (mqd == -1) {printf("open failed!!!\n");return 0;}len = mq_receive(mqd, data, attr.mq_msgsize, &prio);data[len] = '\0';mq_close(mqd);printf("msg: %s, msg_len: %d, prio: %d\n", data, attr.mq_msgsize, prio);return 0;}

执行结果:
$ gcc -g -o server server.c -lrt$ gcc -g -o client client.c -lrt$ ./server$ cat /dev/mqueue/msg_testQSIZE:112        NOTIFY:0     SIGNO:0     NOTIFY_PID:0$ ./clientmsg: Hello World!, msg_len: 8192, prio: 2$ ./clientmsg: Hello World, again!, msg_len: 8192, prio: 2$ ./clientmsg: /msg_test, msg_len: 8192, prio: 1$ cat /dev/mqueue/msg_testQSIZE:24         NOTIFY:0     SIGNO:0     NOTIFY_PID:0





原创粉丝点击