《UNIX网络编程:卷2》P61-P66:图5-3、5-4、5-5、5-6、5-7
-------------------------------------------------------------------
图5-3 mq_unlink一个消息队列
/* P61 mqunlink.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <mqueue.h> int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "usage: qmunlink <name>\n"); exit(1); } // 从系统中删除一个消息队列 if (mq_unlink(argv[1]) < 0) { fprintf(stderr, "qm_unlink error: %s\n", strerror(errno)); exit(1); } exit(0); }
在Ubuntu 14.04中运行本程序:
$ ./mqunlink /temp.1234 删除一个消息队列,(这是前一篇文章创建的)
-------------------------------------------------------------------
图5-4 取得并输出某个消息队列
/* P62 mqgetattr.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <mqueue.h> int main(int argc, char *argv[]) { mqd_t mqd; struct mq_attr attr; if (argc != 2) { fprintf(stderr, "usage: mqgetattr <name>\n"); exit(1); } // 打开一个已存在的消息队列 if ((mqd = mq_open(argv[1], O_RDONLY)) < 0) { fprintf(stderr, "mq_open error: %s\n", strerror(errno)); exit(1); } // 获取消息队列属性信息 if (mq_getattr(mqd, &attr) < 0) { fprintf(stderr, "mq_getattr error: %s\n", strerror(errno)); exit(1); } printf("max #msgs = %ld, max #bytes/mes = %ld, " "#currently on queue = %ld\n", attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs); // 关闭消息队列 mq_close(mqd); exit(0); }
运行程序:
$ ./mqcreate /hello.world 创建一个消息队列 $ ./mqgetattr /hello.world 获取消息队列属性 max #msgs = 10, max #bytes/mes = 8192, #currently on queue = 0
-------------------------------------------------------------------
图5-5 改进后的图5-2,允许指定属性
/*P63 mqcreate.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <mqueue.h> #define FILE_MODE (S_IRUSR | S_IWUSR| S_IRGRP | S_IROTH) struct mq_attr attr; int main(int argc, char *argv[]) { int c, flags; mqd_t mqd; flags = O_RDWR | O_CREAT; while ((c = getopt(argc, argv, "em:z:")) != -1) { switch(c) { case 'e': // 允许有一个指定排他性创建的-e选项 flags |= O_EXCL; break; case 'm': // 最大消息数 attr.mq_maxmsg = atol(optarg); break; case 'z': // 最长消息长度 attr.mq_msgsize = atol(optarg); break; } } // getopt在optind中存放下一个待处理参数的下标 if (optind != argc - 1) { fprintf(stderr, "usage: mqcreate [-e] <name>\n"); exit(1); } // 必须同时指定最大消息数和消息大小 if ((attr.mq_maxmsg != 0 && attr.mq_msgsize == 0) || (attr.mq_maxmsg == 0 && attr.mq_msgsize != 0)) { fprintf(stderr, "usage: mqcreate [-e] [-m maxmsg -z msgsize] <name>\n"); exit(1); } // 创建一个消息队列 if ((mqd = mq_open(argv[optind], flags, FILE_MODE, (attr.mq_maxmsg != 0) ? &attr : NULL)) < 0) { fprintf(stderr, "mq_open error: %s\n", strerror(errno)); exit(1); } // 关闭消息队列(消息队列并不会从系统中删除) mq_close(mqd); exit(0); }
在Ubuntu 14.04中运行本程序:
$ ./mqcreate -e -m 1024 -z 8192 /foobar 消息数过大,创建消息队列失败 mq_open error: Invalid argument $ ./mqcreate -e -m 10 -z 8192 /foobar $ ./mqgetattr /foobar max #msgs = 10, max #bytes/mes = 8192, #currently on queue = 0
-------------------------------------------------------------------
图5-6 mqsend程序
/* P65 mqsend.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <mqueue.h> int main(int argc, char *argv[]) { mqd_t mqd; void *ptr; size_t len; unsigned int prio; if (argc != 4) { fprintf(stderr, "usage: mqsend <name> <#bytes> <priority>\n"); exit(1); } len = atoi(argv[2]); prio = atoi(argv[3]); // 打开消息队列 if ((mqd = mq_open(argv[1], O_WRONLY)) < 0) { fprintf(stderr, "mq_open error: %s\n", strerror(errno)); exit(1); } // 分配存储空间,函数calloc会把该缓冲区初始化为0 if((ptr = calloc(len, sizeof(char))) == NULL) { fprintf(stderr, "calloc error: %s\n", strerror(errno)); exit(1); } // 发送消息一条消息到指定队列中 if (mq_send(mqd, ptr, len, prio) < 0) { fprintf(stderr, "mq_send error: %s\n", strerror(errno)); exit(1); } exit(0); }
-------------------------------------------------------------------
图5-7 mqreceive程序
/* P66 mqreceive.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <mqueue.h> int main(int argc, char *argv[]) { int c, flags; mqd_t mqd; ssize_t n; unsigned int prio; void *buff; struct mq_attr attr; flags = O_RDONLY; while ((c = getopt(argc, argv, "n")) != -1) { switch(c) { case 'n': // 指定非阻塞属性 flags |= O_NONBLOCK; break; } } if (optind != argc - 1) { fprintf(stderr, "usage: mqreceiver [-n] <name>\n"); exit(1); } // 打开消息队列 if ((mqd = mq_open(argv[optind], flags)) < 0) { fprintf(stderr, "mq_open error: %s\n", strerror(errno)); exit(1); } // 获取消息队列属性信息 mq_getattr(mqd, &attr); // 分配存储空间 if ((buff = malloc(attr.mq_msgsize)) == NULL) { fprintf(stderr, "malloc error: %s\n", strerror(errno)); exit(1); } // 从消息队列中读取消息 if ((n = mq_receive(mqd, buff, attr.mq_msgsize, &prio)) < 0) { fprintf(stderr, "mq_receive error: %s\n", strerror(errno)); exit(1); } printf("read %ld bytes, priority = %u\n", n, prio); exit(0); }
-------------------------------------------------------------------
Makefile文件
mqcreate: gcc mqcreate.c -o mqcreate -Wall -lrt mqunlink: gcc mqunlink.c -o mqunlink -Wall -lrt mqgetattr: gcc mqgetattr.c -o mqgetattr -Wall -lrt mqsend: gcc mqsend.c -o mqsend -Wall -lrt mqreceive: gcc mqreceive.c -o mqreceive -Wall -lrt all: make mqcreate mqunlink mqgetattr mqsend mqreceive clean: rm mqcreate mqunlink mqgetattr mqsend mqreceive
-------------------------------------------------------------------
编译:
$ make all
运行程序:
$ ./mqcreate /test1 创建并取得属性 $ ./mqgetattr /test1 max #msgs = 10, max #bytes/mes = 8192, #currently on queue = 0 $ ./mqsend /test1 100 99999 以无效的优先级发送 mq_send error: Invalid argument $ ./mqsend /test1 100 6 100字节,优先级为6 $ ./mqsend /test1 50 18 50字节,优先级为18 $ ./mqsend /test1 33 18 33字节,优先级为18 $ ./mqreceive /test1 read 50 bytes, priority = 18 返回优先级最高的最早消息 $ ./mqreceive /test1 read 33 bytes, priority = 18 $ ./mqreceive /test1 read 100 bytes, priority = 6 $ ./mqreceive -n /test1 指定非阻塞,队列为空 mq_receive error: Resource temporarily unavailable