• IPC通信:Posix消息队列读,写


    创建消息队列的程序:

     1 #include <stdio.h>  
     2 #include <stdlib.h> 
     3 #include <mqueue.h>   //头文件
     4 #include <sys/types.h>  
     5 #include <sys/stat.h>  
     6 #include <unistd.h>  
     7 #include <fcntl.h>  
     8 #include <errno.h>   
     9 
    10 #define MQ_NAME ("/tmp")  
    11 #define MQ_FLAG (O_RDWR | O_CREAT | O_EXCL) // 创建MQ的flag  
    12 #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建MQ的权限  
    13 
    14 int main()  
    15 
    16 {  
    17     mqd_t posixmq;  
    18     int rc = 0;  
    19 
    20     /*  
    21     函数说明:函数创建或打开一个消息队列  
    22     返回值:成功返回消息队列描述符,失败返回-1,错误原因存于errno中  
    23     */ 
    24     posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, NULL);  
    25 
    26     if(-1 == posixmq)  
    27     {  
    28         perror("创建MQ失败");  
    29         exit(1);  
    30     }  
    31 
    32     /*  
    33     函数说明:关闭一个打开的消息队列,表示本进程不再对该消息队列读写  
    34     返回值:成功返回0,失败返回-1,错误原因存于errno中  
    35     */ 
    36     rc = mq_close(posixmq);  
    37     if(0 != rc)  
    38     {  
    39         perror("关闭失败");  
    40         exit(1);  
    41     }  
    42 
    43 #if 0
    44     /*  
    45     函数说明:删除一个消息队列,好比删除一个文件,其他进程再也无法访问  
    46     返回值:成功返回0,失败返回-1,错误原因存于errno中  
    47     */
    48     rc = mq_unlink(MQ_NAME);  
    49     if(0 != rc)  
    50     {  
    51         perror("删除失败");  
    52         exit(1);  
    53     }  
    54 
    55     return 0;
    56 #endif  
    57 } 

    编译并执行:

    1 root@linux:/mnt/hgfs/C_libary# gcc -o crtmq crtmq.c -lrt
    2 root@linux:/mnt/hgfs/C_libary# ./crtmq
    3 程序并没有删除消息队列(消息队列有随内核持续性),如再次执行该程序则会给出错误信息: 
    4 root@linux:/mnt/hgfs/C_libary# ./crtmq 
    5 创建MQ失败: File  exit(0)

    向消息队列写消息的程序:

    消息队列的读写主要使用下面两个函数: 
    /*头文件*/
    #include <mqueue.h>  
    
    /*返回:若成功则为消息中字节数,若出错则为-1 */ 
    int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); 
    
    /*返回:若成功则为0, 若出错则为-1*/ 
    ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);  
    
    /*消息队列属性结构体*/
    struct mq_attr { 
       long mq_flags;       /* Flags: 0 or O_NONBLOCK */ 
       long mq_maxmsg;      /* Max. # of messages on queue */ 
       long mq_msgsize;     /* Max. message size (bytes) */ 
       long mq_curmsgs;     /* # of messages currently in queue */ 
    };
     1 #include <stdio.h>  
     2 #include <stdlib.h>  
     3 #include <mqueue.h>  
     4 #include <sys/types.h>  
     5 #include <sys/stat.h>  
     6 #include <unistd.h>  
     7 #include <fcntl.h>  
     8 #include <errno.h>  
     9    
    10 /*向消息队列发送消息,消息队列名及发送的信息通过参数传递*/ 
    11 int main(int argc, char *argv[])  
    12 {  
    13     mqd_t mqd;  
    14     char *ptr;  
    15     size_t len;  
    16     unsigned int prio;  
    17     int rc;  
    18 
    19     if(argc != 4)  
    20     {  
    21         printf("Usage: sendmq <name> <bytes> <priority>\n");  
    22         exit(1);  
    23     }  
    24 
    25     len = atoi(argv[2]);  
    26     prio = atoi(argv[3]);    
    27 
    28     //只写模式找开消息队列  
    29     mqd = mq_open(argv[1], O_WRONLY);  
    30     if(-1 == mqd)  
    31     {  
    32         perror("打开消息队列失败");  
    33         exit(1);  
    34     }  
    35 
    36     // 动态申请一块内存  
    37     ptr = (char *) calloc(len, sizeof(char));  
    38     if(NULL == ptr)  
    39     {  
    40         perror("申请内存失败");  
    41         mq_close(mqd);  
    42         exit(1);  
    43     }  
    44    
    45     /*向消息队列写入消息,如消息队列满则阻塞,直到消息队列有空闲时再写入*/ 
    46     rc = mq_send(mqd, ptr, len, prio);  
    47     if(rc < 0)  
    48     {  
    49         perror("写入消息队列失败");  
    50         mq_close(mqd);  
    51         exit(1);  
    52     }     
    53 
    54     // 释放内存  
    55     free(ptr);  
    56     return 0;  
    57 } 

    编译并执行:

    1 root@linux:/mnt/hgfs/C_libary# gcc -o sendmq sendmq.c -lrt
    2 root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 15
    3 root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 16
    4 root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 17
    5 root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp 30 18

      上面先后向消息队列“/tmp”写入了四条消息,因为先前创建的消息队列只允许存放3条消息,本次第四次写入时程序会阻塞。直到有另外进程从消息队列取走消息后本次写入才成功返回。

    读消息队列:

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <mqueue.h>  
    #include <sys/types.h>  
    #include <sys/stat.h>  
    #include <unistd.h>  
    #include <fcntl.h>  
    #include <errno.h>  
    
    /*读取某消息队列,消息队列名通过参数传递*/ 
    int main(int argc, char *argv[])  
    {  
        mqd_t mqd;  
        struct mq_attr attr;  
        char *ptr;  
        unsigned int prio;  
        size_t n;  
        int rc;  
    
        if(argc != 2)  
        {  
            printf("Usage: readmq <name>\n");  
            exit(1);  
        }  
    
        /*只读模式打开消息队列*/ 
        mqd = mq_open(argv[1], O_RDONLY);  
        if(mqd < 0)  
        {  
            perror("打开消息队列失败");  
            exit(1);  
        }     
    
        // 取得消息队列属性,根据mq_msgsize动态申请内存  
        rc = mq_getattr(mqd, &attr);  
        if(rc < 0)  
        {  
            perror("取得消息队列属性失败");  
            exit(1);  
        }  
    
        /*动态申请保证能存放单条消息的内存*/ 
        ptr = calloc(attr.mq_msgsize, sizeof(char));  
        if(NULL == ptr)  
        {  
            printf("动态申请内存失败\n");  
            mq_close(mqd);  
            exit(1);  
        }     
    
        /*接收一条消息*/ 
        n = mq_receive(mqd, ptr, attr.mq_msgsize, &prio);  
        if(n < 0)  
        {  
            perror("读取失败");  
            mq_close(mqd);  
            free(ptr);  
            exit(1);  
        }  
        
        printf("读取 %ld 字节\n  优先级为 %u\n", (long)n, prio);     
        return 0;  
    } 

    编译并执行:

     1 root@linux:/mnt/hgfs/C_libary# vi readmq.c
     2 root@linux:/mnt/hgfs/C_libary# vi readmq.c
     3 root@linux:/mnt/hgfs/C_libary# gcc -o readmq readmq.c -lrt
     4 root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
     5 读取 30 字节
     6   优先级为 18
     7 root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
     8 读取 30 字节
     9   优先级为 17
    10 root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
    11 读取 30 字节
    12   优先级为 16
    13 root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
    14 读取 30 字节
    15     优先级为 15
    16 root@linux:/mnt/hgfs/C_libary# ./readmq /tmp

      程序执行五次,第一次执行完,先前阻塞在写处的程序成功返回。第五次执行,因为消息队列已经为空,程序阻塞。直到另外的进程向消息队列写入一条消息。另外,还可以看出Posix消息队列每次读出的都是消息队列中优先级最高的消息。

     

  • 相关阅读:
    北邮《数据库原理与应用》应用阶段作业二带答案
    指针(字符串排序)
    Mysql—二进制日志(binlog)
    Mysql—日志文件系统
    7zip批量压缩,并批量改.jar
    解决:Windows 强制升级为8.1之后 Mysql连接不上, VisualSVN Server无服务
    推荐一个很好的博客
    c/c++ 继承与多态 继承时如何改变个别成员的访问属性
    c/c++ 继承与多态 友元与继承
    c/c++ 继承与多态 由子类向父类的转换规则
  • 原文地址:https://www.cnblogs.com/polestar/p/2451198.html
Copyright © 2020-2023  润新知