您的位置:首页 > 其它

IPC-----POSIX消息队列

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

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

#include<fcntl.h>/*ForO_*constants*/ #include<sys/stat.h>/*Formodeconstants*/ #include<mqueue.h> mqd_tmq_open(constchar*name,intoflag); //专用于打开一个消息队列 mqd_tmq_open(constchar*name,intoflag,mode_tmode,structmq_attr*attr);
参数:

name:消息队列名字;

 注意-PosixIPC名字限制:

  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;注意:使用此函数后,编译链接时需要linkwith-lrt

2、关闭一个消息队列

  #include<mqueue.h>

  intmq_close(mqd_tmqdes);

  Linkwith-lrt.

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

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

3、删除一个消息队列
#include<mqueue.h> intmq_unlink(constchar*name); Linkwith-lrt.
删除会马上发生,即使该队列的描述符引用计数仍然大于0。 参数为mq_open()函数第一个参数。 4、获取/设置消息队列属性
  #include<mqueue.h>

  intmq_getattr(mqd_tmqdes,structmq_attr*attr);

  intmq_setattr(mqd_tmqdes,structmq_attr*newattr,structmq_attr*oldattr);

  Linkwith-lrt.

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

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

structmq_attr{ longmq_flags;/*Flags:0orO_NONBLOCK*/ longmq_maxmsg;/*Max.#ofmessagesonqueue*/ longmq_msgsize;/*Max.messagesize(bytes)*/ longmq_curmsgs;/*#ofmessagescurrentlyinqueue*/ };

  参数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> intmq_send(mqd_tmqdes,constchar*msg_ptr,size_tmsg_len,unsignedmsg_prio); ssize_tmq_receive(mqd_tmqdes,char*msg_ptr,size_tmsg_len,unsigned*msg_prio); Linkwith-lrt.


  参数msg_ptr为指向消息的指针。
  msg_len为消息长度,该值不能大于属性值中mq_msgsize的值。
  msg_prio为优先级,消息在队列中将按照优先级大小顺序来排列消息。
  如果消息队列已满,mq_send()函数将阻塞,直到队列有可用空间再次允许放置消息或该调用被信号打断;如果O_NONBLOCK被指定,mq_send()那么将不会阻塞,而是返回EAGAIN错误。
  如果队列空,mq_receive()函数将阻塞,直到消息队列中有新的消息;如果O_NONBLOCK被指定,mq_receive()那么将不会阻塞,而是返回EAGAIN错误。

6、[b]建立/删除异步通知事件[/b]
  Posix消息队列容许异步事件通知,以告知何时有一个消息放置到某个空消息队列中,这种通知有两种方式可以选择:

  (1)产生一个信号

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

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

  #include<mqueue.h>

  intmq_notify(mqd_tmqdes,conststructsigevent*sevp);

  Linkwith-lrt.

 参数sevp:  (1)如果sevp参数为非空,那么当前进程希望在有一个消息到达所指定的先前为空的对列时得到通知。
 (2)如果sevp参数为空,而且当前进程被注册为接收指定队列的通知,那么已存在的注册将被撤销。
 (3)任意时刻只有一个进程可以被注册为接收某个给定队列的通知。
 (4)当有一个消息到达先前为空的消息队列,而且已有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用中的前提下,通知才会发出。即说明,在mq_receive调用中的阻塞比任何通知的注册都优先。
 (5)当前通知被发送给它的注册进程时,其注册已被撤销。该进程必须再次调用mq_notify以重新注册。
//sigevent结构体
structsigevent
{
intsigev_notify;/*Notificationmethod*/
intsigev_signo;/*Notificationsignal*/
unionsigvalsigev_value;/*Datapassedwithnotification*/
void(*sigev_notify_function)(unionsigval);/*Functionusedforthreadnotification(SIGEV_THREAD)*/
void*sigev_notify_attributes;/*Attributesfornotificationthread(SIGEV_THREAD)*/
pid_tsigev_notify_thread_id;/*IDofthreadtosignal(SIGEV_THREAD_ID)*/
};
unionsigval/*Datapassedwithnotification*/
{
intsival_int;/*Integervalue*/
void*sival_ptr;/*Pointervalue*/
};
  sigev_notify代表通知的方式:一般常用两种取值:SIGEV_SIGNAL,以信号方式通知;SIGEV_THREAD,以线程方式通知

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

  sigev_signo:信号的代码

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

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

  sigev_notify_function

  sigev_notify_attributes


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

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

  MountingthemessagequeuefilesystemOnLinux,messagequeuesarecreatedinavirtualfilesystem.

  (Otherimplementationsmayalsoprovidesuchafeature,butthedetailsarelikelytodiffer.)This

  filesystemcanbemounted(bythesuperuser,注意是使用root用户才能成功)usingthefollowingcommands:

  mkdir/dev/mqueue

  mount-tmqueuenone/dev/mqueue

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

  cat/dev/mqueue/abc

  rmabc

  还可umount该文件系统

  umount/dev/mqueue



细说linuxIPC(九):posix消息队列http://blog.csdn.net/shallnet/article/details/41749613LinuxIPC实践(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: