IPC-----POSIX消息队列

  消息队列可以认为是一个链表。进程(线程)可以往里写消息,也可以从里面取出消息。一个进程可以往某个消息队列里写消息,然后终止,另一个进程随时可以从消息队列里取走这些消息。这里也说明了,消息队列具有随内核的持续性,也就是系统不重启,消息队列永久存在。

1、创建/获取一个消息队列

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <mqueue.h>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:  消息队列名字;

 注意-Posix IPC名字限制:

  1. 必须以”/”开头, 并且后面不能还有”/”, 形如:/file-name(为了便于移植);

  2. 名字长度不能超过NAME_MAX

oflag: 与open函数类型, 可以是O_RDONLY, O_WRONLY, O_RDWR, 还可以按位或,除此之外还可以指定O_CREAT(没有该对象则创建)、O_EXCL(如果O_CREAT指定,但name不存在,

    就返回错误),O_NONBLOCK(以非阻塞方式打开消息队列,在正常情况下mq_receive和mq_send函数会阻塞的地方,使用该标志打开的消息队列会返回EAGAIN错误)。

 当操作一个新队列时,使用O_CREAT标识,此时后面两个参数需要被指定,

mode: mode为指定权限位

attr: 指定新创建消息队列的属性;

返回值:

成功: 返回消息队列文件描述符;

失败: 返回-1;注意:使用此函数后,编译链接时需要 link with -lrt

2、关闭一个消息队列

  #include <mqueue.h>

  int mq_close(mqd_t mqdes);

  Link with -lrt.

  关闭之后调用进程不在使用该描述符,但消息队列不会从系统中删除,进程终止时,会自动关闭已打开的消息队列,和调用mq_close一样。

 参数为mq_open()函数返回的值。

3、删除一个消息队列
 #include <mqueue.h>
 int mq_unlink(const char *name);
 Link with -lrt.
删除会马上发生,即使该队列的描述符引用计数仍然大于0。参数为mq_open()函数第一个参数。

4、获取/设置消息队列属性

  #include <mqueue.h>

  int mq_getattr(mqd_t mqdes, struct mq_attr *attr);

  int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);

  Link with -lrt.

  参数mqdes为mq_open()函数返回的消息队列描述符。


  参数attr、newattr、oldattr分别为为消息队列属性结构体指针、需要设置的属性结构体指针和原来的属性结构体指针;

          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 */
           };

  参数mq_flags在mq_open时被初始化(oflag参数),其值为0 或者 O_NONBLOCK。

  参数mq_maxmsg和mq_msgsize在mq_open时在参数attr中初始化设置,mq_maxmsg是指消息队列能够保存的消息数;mq_msgsize为消息的最大长度。

  参数mq_curmsgs为消息队列当前保存的消息数。

  mq_getattr()函数把队列当前属性填入attr所指向的结构体。

  mq_setattr()函数只能设置mq_flags属性,另外的域会被自动忽略,mq_maxmsg和mq_msgsize的设置需要在mq_open当中来完成, 参数oldattr会和函数mq_getattr函数中参数attr相同的值。

5、发送/读取消息

  mq_send() 函数 和mq_receive()函数分别用于向消息队列放置和取走消息。

       #include <mqueue.h>
       int mq_send(mqd_t mqdes, const char *msg_ptr,   size_t msg_len, unsigned msg_prio);
       ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,  size_t msg_len, unsigned *msg_prio);
       Link with -lrt.

  参数msg_ptr为指向消息的指针。

  msg_len为消息长度,该值不能大于属性值中mq_msgsize的值。

  msg_prio为优先级,消息在队列中将按照优先级大小顺序来排列消息。

  如果消息队列已满,mq_send()函数将阻塞,直到队列有可用空间再次允许放置消息或该调用被信号打断;如果O_NONBLOCK被指定,mq_send()那么将不会阻塞,而是返回EAGAIN错误。

  如果队列空,mq_receive()函数将阻塞,直到消息队列中有新的消息;如果O_NONBLOCK被指定,mq_receive()那么将不会阻塞,而是返回EAGAIN错误。

 
6、建立/删除异步通知事件

  Posix消息队列容许异步事件通知,以告知何时有一个消息放置到某个空消息队列中,这种通知有两种方式可以选择:

  (1)产生一个信号

  (2)创建一个线程来执行一个指定的函数

   注意: 这种注册的方式只是在消息队列从空到非空时才产生消息通知事件, 而且这种注册方式是一次性的!

  #include <mqueue.h>

  int mq_notify(mqd_t mqdes, const struct sigevent *sevp);

  Link with -lrt.

 参数sevp: (1)如果sevp参数为非空,那么当前进程希望在有一个消息到达所指定的先前为空的对列时得到通知。

 (2)如果sevp参数为空,而且当前进程被注册为接收指定队列的通知,那么已存在的注册将被撤销。

 (3)任意时刻只有一个进程可以被注册为接收某个给定队列的通知。

 (4)当有一个消息到达先前为空的消息队列,而且已有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用中的前提下,通知才会发出。即说明,在mq_receive调用中的阻塞比任何通知的注册都优先。

 (5)当前通知被发送给它的注册进程时,其注册已被撤销。该进程必须再次调用mq_notify以重新注册。

//sigevent结构体
struct sigevent
{
    int          sigev_notify; /* Notification method */
    int          sigev_signo;  /* Notification signal */
    union sigval sigev_value;  /* Data passed with notification */
    void       (*sigev_notify_function) (union sigval);  /* Function used for thread notification (SIGEV_THREAD) */
    void        *sigev_notify_attributes; /* Attributes for notification thread (SIGEV_THREAD) */
    pid_t        sigev_notify_thread_id; /* ID of thread to signal (SIGEV_THREAD_ID) */
};
union sigval            /* Data passed with notification */
{
    int     sival_int;         /* Integer value */
    void   *sival_ptr;         /* Pointer value */
};

  sigev_notify代表通知的方式: 一般常用两种取值:SIGEV_SIGNAL, 以信号方式通知; SIGEV_THREAD, 以线程方式通知

  如果以信号方式通知: 则需要设定一下两个参数:

  sigev_signo: 信号的代码

  sigev_value: 信号的附加数据(实时信号)

  如果以线程方式通知: 则需要设定以下两个参数:

   sigev_notify_function

   sigev_notify_attributes


  查看已经成功创建的Posix消息队列

  #其存在与一个虚拟文件系统中, 需要将其挂载到系统中才能查看

  Mounting the message queue filesystem On Linux, message queues are created in a virtual filesystem.

  (Other implementations may also  provide such a feature, but the details are likely to differ.)  This

  file system can be mounted (by the superuser, 注意是使用root用户才能成功) using the following commands:

  mkdir /dev/mqueue

  mount -t mqueue none /dev/mqueue

  还可以使用cat查看该消息队列的状态, rm删除:

  cat /dev/mqueue/abc

  rm abc

  还可umount该文件系统

  umount /dev/mqueue


细说linux IPC(九):posix消息队列        http://blog.csdn.net/shallnet/article/details/41749613Linux IPC实践(7) --Posix消息队列        http://blog.csdn.net/zjf280441589/article/details/43878041Posix消息队列——mq_notify函数            http://www.xuebuyuan.com/1694248.htmlPOSIX消息队列的异步通信机制               http://blog.csdn.net/bat603/article/details/19978025
时间: 2024-10-15 11:04:10

IPC-----POSIX消息队列的相关文章

UNIX IPC: POSIX 消息队列

首先在我的MAC OSX上试了一下虽然有_POSIX_MESSAGE_PASSING的宏定义,但是用gcc编译会提示没有mqueue.h头文件,先放一边.在Ubuntu上使用正常,不过POSIX消息队列通过ipcs命令是看不到的,需要通过如下方式进行查看: mount -t mqueue none /mnt ls -al /mnt ls列出的文件即为程序中创建的POSIX消息队列,消息队列的名称需要以“/”开头否则会提示参数非法.通过cat查看这个文件可以知道这个队列的一些参数如: [email

UNIX IPC: POSIX 消息队列 与 信号

POSIX消息队列可以注册空队列有消息到达时所触发的信号,而信号触发对应的信号处理函数. 下面是一份基本的消息队列和信号处理结合的代码(修改自UNIX网络编程:进程间通信) #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <mqueue.h> #include

Linux进程间通信(IPC)编程实践(十二)Posix消息队列--基本API的使用

posix消息队列与system v消息队列的差别: (1)对posix消息队列的读总是返回最高优先级的最早消息,对system v消息队列的读则可以返回任意指定优先级的消息. (2)当往一个空队列放置一个消息时,posix消息队列允许产生一个信号或启动一个线程,system v消息队列则不提供类似机制. 队列中的每个消息具有如下属性: 1.一个无符号整数优先级(posix)或一个长整数类型(system v) 2.消息的数据部分长度(可以为0) 3.数据本身(如果长度大于0) Posix消息队

Linux IPC实践(7) --Posix消息队列

1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <mqueue.h> mqd_t mq_open(const char *name, int oflag); //专用于打开一个消息队列 mqd_t mq_open(const char *name, int oflag, mode_t mode

Linux环境编程之IPC进程间通信(五):Posix消息队列1

对于管道和FIFO来说,必须应该先有读取者存在,否则先有写入者是没有意义的.而消息队列则不同,它是一个消息链表,有足够写权限的线程可往别的队列中放置消息,有足够读权限的线程可从队列中取走消息.每个消息都是一个记录,它由发送者赋予一个优先级.在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达.消息队列是随内核的持续性,一个进程可以往某个队列写入一些消息,然后终止,再让另外一个进程在以后的某个时刻读出这些消息.这跟管道和FIFO不一样,当一个管道或FIFO的最后一次关闭时

Unix IPC之Posix消息队列(1)

部分参考:http://www.cnblogs.com/Anker/archive/2013/01/04/2843832.html IPC对象的持续性:http://book.51cto.com/art/201006/207275.htm 消息队列可以认为是一个消息链表,某个进程往一个消息队列中写入消息之前,不需要另外某个进程在该队列上等待消息的达到,这一点与管道和FIFO相反.Posix消息队列与System V消息队列的区别如下: 1. 对Posix消息队列的读总是返回最高优先级的最早消息,

细说linux IPC(九):posix消息队列

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 消息队列可以看作一系列消息组织成的链表,一个程序可以往这个链表添加消息,另外的程序可以从这个消息链表读走消息. mq_open()函数打开或创建一个posix消息队列. #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode cons

进程间通信(IPC)之消息队列

★IPC方法包括管道(PIPE).消息队列(Message_Queue).旗语.共用内存(ShareMemory)以及套接字(Socket).进 程间通信主要包括了管道.系统IPC(包括了消息队列.信号以及共享存储).套接字(SOCKET).此文将详细叙述消息队列的相 关内容. ★产生原因: 所谓消息队列,其实就是消息(数据)传输过程中保存的容器.既然有了管道通信的方式,何必又有消息队列呢? 因为根据管道的特性,我们知道其在一定程度上存在或多或少的局限性,首先匿名管道以及命名管道是随进程的,进

[转]Linux进程通信之POSIX消息队列

进程间的消息队列可以用这个实现,学习了下. http://blog.csdn.net/anonymalias/article/details/9799645?utm_source=tuicool&utm_medium=referral 消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据. 消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点: 一个进程向消息队列写入消息之前,并不需要某个进程在该队列上等待该消息的到达,而管道和FIFO是相

Posix消息队列相关函数

Posix消息队列(message queue) IPC函数中常用的参数取值: 打开或创建POSIX IPC对象所用的各种oflag常值o_RDONLY   只读O_WRONLY   只写O_RDWD     读写O_CREAT    若不存在则创建,存在则引用O_EXCL     排他性创建,需要和O_CREAT一起使用,当对象不存在时才创建,否则返回EEXIST错误O_NONBLOCK 非阻塞模式O_TRUNC    若已存在则截短 创建新的IPC对象所用的mode常值: S_IRUSR