读书笔记:第5章 Posix消息队列 (2)

《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

你可能感兴趣的:(读书笔记,《UNIX网络编程》)