Posix消息队列和System V消息队列
msgsnd(intmsqid,const void * ptr,size_t length,int flag)中long类型的消息类型不能为0,否则发送会失败。
msgrcv(int msqid,void*ptr ,size_t length,long type ,int flag)中ptr必须是一个结构体的地址,并且该结构体第一个成员要是long类型。否则会接收失败。
消息队列
消息队列可以认为是一个消息链表。有足够写权限的线程就可往队列中放置消息,有足够读权限的线程就可以从队列中取走消息。每个消息是一个记录,他有发送者赋予一个优先级。在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达。
Posix消息队列和System V系统的消息队列区别:
1、对Posix消息队列的读总是返回最高优先级的最早消息,对System V消息队列得读则可以返回任意指定优先级的消息
2、当往一个队列放置一个消息时,Posix消息队列允许产生一个信号或启动一个线程,System V消息队列则不提供类似的机制
消息的属性:
1、一个无符号整数优先级(Posix)或是长整类型(SystemV)
2、消息的数据部分长度
3、数据本身
(System V系统发送消息时需要定义消息的结构,而Posix系统不需要定义这样的结构)
Posxi 消息队列
mq_open 创建一个新消息队列或是打开一个已经存在的消息队列,返回值成为消息队列描述字。
mq_close 关闭已打开的消息队列。
mq_unlink 从系统删除消息队列。
每个消息队列有四个属性,有mq_getattr获得这些属性,mq_setattr设置其中某个属性
mq_send:用于往一个队列中放置一个消息
mq_receive:用于往一个队列中取走一个消息,该函数总是返回所指定队列中最高优先级的最早的消息,而且该优先级能随该消息的内容及长度一同返回。
每个消息有一个优先级,他是一个小于MQ_PRIO_MAX的无符号整数,Posix要求这个上限至少为32 。
mq_notify 该函数给指定队列建立或删除异步事件通知
int mq_notify(mqd_t mqdes ,const struct sigevent *notification);
使用规则:
1、如果notification参数非空,那么当前进程希望在有一个消息到达所指定队列而且该队列先前为空时得到通知。我们说该进程被注册为接收该队列的通知
2、如果notification参数为空指针,而且当前进程目前被注册为接收所指定队列的通知,那么现有注册将被撤销。
3、任意时刻只有一个进程可以被注册为接收某个给定队列的通知。
4、当有一个消息到达某个先前为空的队列,而且已有一个进程被注册为接收该队列的通知时,只有没有任何进程阻赛在该队列的mq_receive调用的前提下,通知才会发生。这就是说,在mq_revcive调用中的阻赛比任何通知的注册都优先。
5、当该通知被发送给他的注册进程时,其注册即被撤销,该进程必须再次调用该函数以重新注册。
(当消息队列有消息来到时该函数产生一个信号或时线程,信号或线程是由struct sigevent 参数指定的)
System V 的消息队列
System V消息队列使用消息队列标示符标示。具有足够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息。
对于系统中的每个消息队列,内核维护一个信息结构,struct msqid_ds
msgget函数用于创建一个新的消息队列或访问一个已经存在的消息队列msgget(key_t key ,intoflag ),在创健一个新消息队列时,msqid_ds结构将被初始化。
msgsnd函数往msgget函数建立的消息队列中放置一个消息,
msgsnd(int msqid,const void * ptr,size_t length,int flag);其中ptr是一个结构指针,该结构具有如下的模板struct msgbuf{long mtype ;char mtext[1]}; 该模板可以在<sys/msg.h>;中找到
其中消息类型必须大于0,msgbuf 结构定义中的名字mtext不大确切;消息的数据部分并不局限于文本,任何形式的数据都是允许的,无论是二进制数据还是文本。内核根本不解释消息数据的内容。使用模板的说法描述这个结构,因为ptr所指向的只是一个含有消息类型的长整数,消息本身则紧跟在他之后。不过大多数应用并不使用msgbuf结构的这个定义,因为其数据量通常是不够的。大多数应用定义自己的消息结构,其数据部分根据应用的需要定义。例如:应用需要交换由一个16位整数后跟一个8字节字符数组构成的消息,那么它的结构如下:typedef struct my_msgbuf{long mytype ; int16_t mshort; char mchar[8];}
msgsnd 的length参数以字节为单位指定代发送消息的长度。这是位于长整数消息类型之后的用户自定义数据的长度。该长度可以是0。如上例长度为 sizeof(structmy_msgbuf)-sizeof(long).
msgrcv(int msqid,void *ptr,size_t length,long type ,int flag)函数中ptr参数指定所接受消息的存放位置。和msgsnd一样,该指针指向紧挨在真正的消息数据之前返回的长整数类型字段(就是定义的消息结构体)。Length指定由ptr指向的缓冲区中数据部分的大小。这是该函数能返回的最大数据量。该长度不包括长整数类型字段。Type指定希望从所给定的队列中读出什么样的消息:
如果type为0,那就返回该队列中的第一个消息。
如果type大于0,那就返回其类型值为type的第一个消息。
如果type小于0,那就返回其类型值小于或等于type参数的绝对值的消息中类型值得最小的第一个消息。
Msgrcv的flag参数指定所请求类型的消息不在所指定的队列中时怎么办。成功返回时,msgrcv返回所接收消息中数据的字节数。他不包括也通过ptr参数返回的长整数消息类型所需的几个字节。
Msgctl函数提供在一个消息队列上的各种控制操作。Msgctl(int msqid ,int cmd,struct msqid_de *buff);
三个命令:IPC_RMID 从系统删除指定的消息队列;
IPC_SET 给所指定的消息队列设置其msqid_ds结构的成员;
IPC_STAT 给调用者返回对应所指定消息队列的当前msqid_ds结构