消息队列 在UNIX的SystemV版本,AT&T引进了三种新形式的IPC功能(消息队列、信号量、以及共享内存)。但BSD版本的UNIX使用套接口作为主要的IPC形式。Linux系统同时支持这两个版本。 系统调用msgget() 如果希望创建一个新的消息队列,或者希望存取一个已经存在的消息队列,你可以使用系统调用msgget()。 系统调用:msgget(); 原型:int msgget(key_t key, int msgflg); 返回值:如果成功,返回消息队列标识符 如果失败,则返回-1:errno=EACCESS(权限不允许) EEXIST(队列已经存在,无法创建) EIDRM(队列标志为删除) ENOENT(队列不存在) ENOMEM(创建队列时内存不够) ENOSPC(超出最大队列限制) 系统调用msgget()中的第一个参数是关键字值(通常是由ftok() 返回的)。然后此关键字值将会和其他已经存在于系统内核中的关键字值比较。这时,打开和存取操作是和参数msgflg中的内容相关的。 IPC_CREAT如果内核中没有此队列,则创建它。 IPC_EXCL当和IPC_CREAT一起使用时,如果队列已经存在,则失败。 如果单独使用IPC_CREAT,则msgget()要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。如果IPC_EXCL和IPC_CREAT一起使用,则msgget()要么创建一个新的消息队列,要么如果队列已经存在则返回一个失败值-1。IPC_EXCL单独使用是没有用处的。 下面看一个打开和创建一个消息队列的例子: int open_queue(key_t keyval) { intqid; if((qid=msgget (keyval, IPC_CREAT|0660))==-1) { return(-1); } return(qid); } 系统调用msgsnd() 一旦我们得到了队列标识符,我们就可以在队列上执行我们希望的操作了。如果想要往队列中发送一条消息,你可以使用系统调用msgsnd(): 系统调用:msgsnd(); 原型:int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg); 返回值:如果成功,0。 如果失败,-1:errno=EAGAIN(队列已满,并且使用了IPC_NOWAIT) EACCES(没有写的权限) EFAULT(msgp地址无效) EIDRM(消息队列已经删除) EINTR(当等待写操作时,收到一个信号) EINVAL(无效的消息队列标识符,非正数的消息类型,或 者无效的消息长度) ENOMEM(没有足够的内存复制消息缓冲区) 系统调用msgsnd()的第一个参数是消息队列标识符,它是由系统调用msgget返回的。第二个参数是msgp,是指向消息缓冲区的指针。参数msgsz中包含的是消息的字节大小,但不包括消息类型的长度(4个字节)。 参数msgflg可以设置为0(此时为忽略此参数),或者使用IPC_NOWAIT。 如果消息队列已满,那么此消息则不会写入到消息队列中,控制将返回到调用进程中。如果没有指明,调用进程将会挂起,直到消息可以写入到队列中。 下面是一个发送消息的程序: int send_message(int qid, struct mymsgbuf *qbuf) { intresult,length; /*The length is essentially the size of the structure minus sizeof(mtype)*/ length=sizeof(structmymsgbuf)-sizeof(long); if((result = msgsnd (qid, qbuf, length, 0))==-1) { return(-1); } return(result); } 系统调用:msgrcv(); 原型:int msgrcv(intmsqid,structmsgbuf*msgp,intmsgsz,longmtype,intmsgflg); 返回值:如果成功,则返回复制到消息缓冲区的字节数。 如果失败,则返回-1:errno=E2BIG(消息的长度大于msgsz,没有MSG_NOERROR) EACCES(没有读的权限) EFAULT(msgp指向的地址是无效的) EIDRM(队列已经被删除) EINTR(被信号中断) EINVAL(msgqid无效,或者msgsz小于0) ENOMSG(使用IPC_NOWAIT,同时队列中的消息无法满足要求) 第一个参数用来指定将要读取消息的队列 。第二个参数代表要存储消息的消息缓冲区 的地址。第三个参数是消息缓冲区的长度,不包括mtype的长度,它可以按照如下的方法计算: msgsz=sizeof(struct mymsgbuf)-sizeof(long); 第四个参数是要从消息队列中读取的消息的类型。如果此参数的值为0,那么队列中最长时间的一条消息将返回,而不论其类型是什么。 |