消息队列

一、Posix消息队列

​1、mq_open,mq_close,mq_unlink

 #include <<span se-mark="1">mqueue.h>

mqd_t mq_open(const char *name, int oflag, ...);

oflag:O_RDONLY​,O_WRONLY,O_RDWR,O_CREAT,O_EXCL,O_NONBLOCK

mq_open的返回值为消息队列描述符。

#include <<span se-mark="1">mqueue.h>

int mq_close(mqd_t mqdes);

​一个进程终止时他所打开的消息队列都会关闭,关闭消息队列之后,消息队列并不在系统中删除。

要从系统中删除需要调用mq_unlink

#include <<span se-mark="1">mqueue.h>

int mq_unlink(const char *name);

name为​mq_open的第一个参数。

每个消息队列保存着当前打开的描述符的引用计数器,当引用计数大于0时name能够删除但是消息队列的析构要等到最后一个mq_close发生才进行。

2、mq_getattr、mq_setattr



​3、mq_send、mq_receive


​mq_receive的len不能小于队列中消息的最大大小,小于该值mq_receive会立即返回EMSGSIZE错误。

​mq_send的prio参数是待发送消息的优先级,其值必须小于MQ_PRIO_MAX,如果mq_receive的priop指针非空,则返回消息的优先级通过该指针存放,如果不需要关注其优先级则mq_send的prio参数指定为0,mq_receive的priop指针为空。

4、消息队列的限制

mq_mqxmsg队列中最大消息数。

mq_msgsize给定消息的最大字节数。

MQ_OPEN_MAX一个进程能够拥有同时打开消息队列的最大数目​

MQ_PRIO_MAX任意消息的最大优先级加1

5、mq_notify

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

  • (1)产生一个信号
  • (2)创建一个线程来执行一个指定的函数

这种通知通过调用mq_notify建立

#include 
int mq_notify(mqd_t mqdes, const struct sigevent* notification);

该函数为指定队列建立或删除异步事件通知

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

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

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

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

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

union sigval{
int     sival_int;          
void    *sival_ptr;         
};

struct sigevent{
int     sigev_notify;       
int     sigev_signo;        

union sigval    sigev_value;

void    (*sigev_notify_function)(union sigval);
pthread_attr_t  *sigev_notify_attributes;


};

二、System V消息队列

ftok()

#include 

#include 

函数原型:

 key_t  ftok( const  char * pathname , int   proj_id  );

参数:

 pathname 就时你指定的文件名(该文件必须是存在而且可以访问的),id是子序号,虽         然为int,但是只有8个比特被使用(0-255)。

返回值: 成功时候返回key_t 类型的key值,失败返回-1

msgget

#include 

#include 

#include 

函数原型: int    msgget ( key_t  key , int  msgflg );

函数描述:建立消息队列

参数:

msgget()函数的第一个参数是消息队列对象的关键字(key),函数将它与已有的消息队列对象的关键字进行比较来判断消息队列对象是否已经创建。而函数进行的具体操作是由第二个参数,msgflg 控制的。它可以取下面的几个值:IPC_CREAT :如果消息队列对象不存在,则创建之,否则则进行打开操作;IPC_EXCL:和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否     则产生一个错误并返回。

返回值:

成功时返回队列ID,失败返回-1,错误原因存于error中

EEXIST (Queue exists, cannot create)EIDRM (Queue is marked for deletion)ENOENT (Queue does not exist)ENOMEM (Not enough memory to create queue)ENOSPC (Maximum queue limit exceeded)

msgsnd函数:将消息送入消息队列

#include 

#include 

#include 

函数原型:int  msgsnd ( int msgid ,  struct msgbuf*msgp , int msgsz, int msgflg );

参数说明:

传给msgsnd()函数的第一个参数msqid 是消息队列对象的标识符(由msgget()函数得

到),第二个参数msgp 指向要发送的消息所在的内存,第三个参数msgsz 是要发送信息     的长度(字节数),可以用以下的公式计算:msgsz = sizeof(struct mymsgbuf) - sizeof(long);第四个参数是控制函数行为的标志,可以取以下的值:0,忽略标志位;IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。

smgbuf结构体定义如下:

struct smgbuf

{

                     long   mtype;

                    char   mtext [x] ;  //长度由msgsz决定

}

msgflg 可设置为 IPC_NOWAIT 。如果消息队列已满或其他情况无法送入消息,则立即 返回 EAGIN

返回: 0 on success

-1 on error: errno = EAGAIN (queue is full, and IPC_NOWAIT was asserted)EACCES (permission denied, no write permission)EFAULT (msgp address isn't accessable – invalid)EIDRM (The message queue has been removed)EINTR (Received a signal while waiting to write)EINVAL (Invalid message queue identifier, nonpositivemessage type, or invalid message size)ENOMEM (Not enough memory to copy message buffer)

msgrcv函数:从消息队列中读取消息

#include 

#include 

#include 

函数定义:int  msgrcv( int  msgid , struct   msgbuf*  msgp ,  int msgsz ,  long msgtyp, int msgflg);

参数:

函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype

指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将之返回。不过这里有一个例外。如果mtype 的值是零的话,函数将不做类型检查而自动返     回队列中的最旧的消息。第五个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果     进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不     被取出。当消息从队列内取出后,相应的消息就从队列中删除了。

msgbuf:结构体,定义如下:

struct msgbuf

{

                      long  mtype ;  //信息种类

                       char   mtest[x];//信息内容   ,长度由msgsz指定

}

msgtyp:  信息类型。 取值如下:

 msgtyp = 0 ,不分类型,直接返回消息队列中的第一项

 msgtyp > 0 ,返回第一项 msgtyp与 msgbuf结构体中的mtype相同的信息

msgtyp <0 , 返回第一项 mtype小于等于msgtyp绝对值的信息

msgflg:取值如下:

IPC_NOWAIT ,不阻塞

IPC_NOERROR ,若信息长度超过参数msgsz,则截断信息而不报错。

返回值:

成功时返回所获取信息的长度,失败返回-1,错误信息存于error
posted @ 2016-11-27 14:20  luizp  阅读(235)  评论(0编辑  收藏  举报