linuxC多进程通讯---POSIX消息队列之内核实现

POSIX消息队列内核实现

•相关数据结构:/usr/include/linux/mqueue.h、/ipc/mqueue.c
•消息队列是消息的链表,存储在内核中,由消息队列标识符标识。
•标识符成为消息队列的ID,程序通过这个句柄可以操作消息队列
•消息属性:
–一个无符号整数优先级
–消息的数据长度(可以为0)
–消息的数据本身
在这里插入图片描述

•system V消息队列内核实现

•相关数据结构:msgid_ds 、/usr/include/linux/msg.h、/ipc/msg.c
•消息队列是消息的链表,存储在内核中,由消息队列标识符标识。
•标识符成为消息队列的ID,程序通过这个句柄可以操作消息队列
•消息属性:
–一个长整数类型(System V)
–消息的数据长度(可以为0)
–消息的数据本身
在这里插入图片描述

•内核中的消息队列描述符

•用来标识打开的消息队列,类似于文件描述符,用来标识打开的文件
•是一个进程级句柄,在内核中实现类似于文件描述符
在这里插入图片描述

•查看设置消息队列的属性

–通过proc文件系统
•$ cat /proc/sys/fs/mqueue/queues_max
•$ cat /proc/sys/fs/mqueue/msg_max
•$ cat /proc/sys/fs/mqueue/msgsize_max
–通过POSIX系统调用接口
•mq_setattr:设置mq_flags
•mq_open:设置mq_maxmsg、mq_msgsize

•POSIX消息队列在Linux上实现的特性

–提供了mqueue类型的虚拟文件系统
•使用另一种I/O模型操作消息队列、获取消息队列的相关信息
•可通过挂载、ls、rm命令来列出和删除消息队列
•$ mkdir /dev/mqueue
•$ mount -t mqueue none /dev/queue
•$ cat /dev/mqueue/my_mqueue
•$ hexdump /dev/mqueue/my_mqueue

•区别和联系

•POSXI消息队列通过设置优先级,总是返回优先级最高的最早消息
•System V 消息队列可以通过消息类型返回指定优先级的任意消息
•POSIX消息队列可以实现异步事件通知
–当有一个消息放置到某个空消息队列中时,这种通知有两种方式可以选择:产生一个信号,或者创建一个线程来执行一个指定的函数
–msgrcv函数接受信息时,若队列为空会阻塞,若设置了NOBLOCK标志,则会不停地调用msgrcv轮询是否有消息到来,非常消耗CPU资源

POSIX 消息队列的优势

•允许一个进程能够在一条消息进入之前的空队列时异步地通过信号或线程的实例化来接收通知
•在Linux上可以使用poll、select、epoll来监控POSIX消息队列
•POSIX的可移植性很差
•POSIX消息队列严格按照优先级排序,而system V可以根据类型来选择消息,灵活性更强

举例

#include <mqueue.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define handle_error(msg)    \
	do{ perror(msg); exit(EXIT_FAILURE);} while (0)

int main(int argc, char *argv[])
{
    mqd_t mq_id;
    struct mq_attr attr;

    attr.mq_maxmsg  = 5;
    attr.mq_msgsize = 4096;
    attr.mq_flags   = O_NONBLOCK;
    mq_id = mq_open("/mqueue_attr", O_CREAT, S_IRUSR | S_IWUSR, &attr);
    if (mq_id == (mqd_t) -1)
        handle_error("mq_open");

    if (mq_getattr(mq_id, &attr) == -1)
        handle_error("mq_getattr");

    printf("Maximum # of messages on queue:   %ld\n", attr.mq_maxmsg);
    printf("Maximum message size:             %ld\n", attr.mq_msgsize);
    printf("Flags:             %ld\n", attr.mq_flags);

  //  attr.mq_maxmsg  = 5;
  //  attr.mq_msgsize = 4096;
    attr.mq_flags   = O_NONBLOCK;
    if (mq_setattr(mq_id, &attr, NULL) == -1)
        handle_error("mq_setattr");
    if (mq_getattr(mq_id, &attr) == -1)
        handle_error("mq_getattr");

    printf("Maximum # of messages on queue:   %ld\n", attr.mq_maxmsg);
    printf("Maximum message size:             %ld\n", attr.mq_msgsize);
    printf("Flags:             %ld\n", attr.mq_flags);

    if (mq_unlink("/mqueue_attr") == -1)
        handle_error("mq_unlink");

    exit(EXIT_SUCCESS);
}

发布了349 篇原创文章 · 获赞 6 · 访问量 9738

猜你喜欢

转载自blog.csdn.net/qq_23929673/article/details/100170878