轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaominglinux消息队列-应用编程-专题讲座writtenby王保明1消息队列基本概念消息队列消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)对比:管道:流管道消息:有边界先进先出可以后进入、先出来消息大小三大限制cat/proc/sys/kernel/msgmax最大消息长度限制cat/proc/sys/kernel/msgmnb消息队列总的字节数cat/proc/sys/kernel/msgmni消息条目数IPC对象数据结构内核为每个IPC对象维护一个数据结构structipc_perm{key_t__key;/*Keysuppliedtoxxxget(2)*/uid_tuid;/*EffectiveUIDofowner*/gid_tgid;/*EffectiveGIDofowner*/uid_tcuid;/*EffectiveUIDofcreator*/gid_tcgid;/*EffectiveGIDofcreator*/unsignedshortmode;/*Permissions*/unsignedshort__seq;/*Sequencenumber*/};structmsqid_ds{structipc_permmsg_perm;/*Ownershipandpermissions*/time_tmsg_stime;/*Timeoflastmsgsnd(2)*/time_tmsg_rtime;/*Timeoflastmsgrcv(2)*/time_tmsg_ctime;/*Timeoflastchange*/unsignedlong__msg_cbytes;/*Currentnumberofbytesinqueue(nonstandard)*/msgqnum_tmsg_qnum;/*Currentnumberofmessages轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaominginqueue*/msglen_tmsg_qbytes;/*Maximumnumberofbytesallowedinqueue*/pid_tmsg_lspid;/*PIDoflastmsgsnd(2)*/pid_tmsg_lrpid;/*PIDoflastmsgrcv(2)*/};消息队列在内核中的表示消息队列函数#includesys/types.h#includesys/ipc.h#includesys/msg.hintmsgget(key_tkey,intmsgflg);intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);msgget函数功能:用来创建和访问一个消息队列原型intmsgget(key_tkey,intmsgflg);参数key:某个消息队列的名字msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的返回值:成功返回一个非负整数,即该消息队列的标识码;失败返回-1轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaomingmsgget函数参数关系图msgctl函数功能:消息队列的控制函数原型intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);参数msqid:由msgget函数返回的消息队列标识码cmd:是将要采取的动作,(有三个可取值)返回值:成功返回0,失败返回-1cmd:将要采取的动作(有三个可取值),分别如下:轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaoming2消息队列基本API消息队列的创建及控制消息队列函数#includesys/types.h#includesys/ipc.h#includesys/msg.hintmsgget(key_tkey,intmsgflg);intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);msgget函数功能:用来创建和访问一个消息队列原型intmsgget(key_tkey,intmsgflg);参数key:某个消息队列的名字msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的返回值:成功返回一个非负整数,即该消息队列的标识码;失败返回-1msgget函数参数关系图轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaomingmsgctl函数功能:消息队列的控制函数原型intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);参数msqid:由msgget函数返回的消息队列标识码cmd:是将要采取的动作,(有三个可取值)返回值:成功返回0,失败返回-1cmd:将要采取的动作(有三个可取值),分别如下:轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaoming消息队列的发送和接受msgsnd函数功能:把一条消息添加到消息队列中原型intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);参数msgid:由msgget函数返回的消息队列标识码msgp:是一个指针,指针指向准备发送的消息,msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个longint长整型msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情返回值:成功返回0;失败返回-1msgflg=IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。消息结构在两方面受到制约。首先,它必须小于系统规定的上限值;其次,它必须以一个longint长整数开始,接收者函数将利用这个长整数确定消息的类型消息结构参考形式如下:structmsgbuf{longmtype;charmtext[100];}msgrcv函数功能:是从一个消息队列接收消息原型ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);参数msgid:由msgget函数返回的消息队列标识码msgp:是一个指针,指针指向准备接收的消息,msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个longint长整型msgtype:它可以实现接收优先级的简单形式msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事返回值:成功返回实际放到接收缓冲区里去的字符个数,失败返回-1msgtype=0返回队列第一条信息msgtype0返回队列第一条类型等于msgtype的消息msgtype0返回队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。msgflg=MSG_NOERROR,消息大小超过msgsz时被截断msgtype0且msgflg=MSG_EXCEPT,接收类型不等于msgtype的第一条消息。轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaoming3消息队列综合api使用同一个进程,使用消息队列structmsg_buf{longmtype;chardata[255];};/*注意long和int在32bit和64bit系统之下是不一样的structmsg_buf{longmtype;chardata[255];};*/intmain(){key_tkey;intmsgid;intret;structmsg_bufmsgbuf;intmsgtype=getpid();key=ftok(./msgfile,'a');printf(key=[%x]\n,key);printf(sizeof(long):%ld,sizeof(int):%d\n,sizeof(long),sizeof(int));msgid=msgget(key,IPC_CREAT|IPC_EXCL|0666);//通过文件对应if(msgid==-1){if(errno==EEXIST){printf(EEXIST:.....\n);key=ftok(./msgfile,'a');轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaomingmsgid=msgget(key,IPC_CREAT|0666);//通过文件对应}else{printf(createerror\n);perror(msget:\n);return-1;}}printf(msgid:%d\n,msgid);msgbuf.mtype=msgtype;//getpid();printf(getpid():%d\n,getpid());strcpy(msgbuf.data,testhaha);ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);if(ret==-1){printf(sendmessageerr\n);perror(senderr);return-1;}sleep(1);memset(&msgbuf,0,sizeof(msgbuf));ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),msgtype,IPC_NOWAIT);if(ret==-1){printf(recvmessageerr\n);perror(dd);return-1;}printf(recvmsg=[%s]\n,msgbuf.data);}轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaoming4消息队列项目开发案例消息队列实现回射客户/服务器