二、
在<sys/msg.h>中,消息队列的数据结构是这样定义的:
struct msgbuf{ long mtype; /*type of message, must>0*/ char mtext[1]; /*message text*/ };
在数据结构msgbuf中共有两个元素:
mtype指消息的类型,它由一个整数来代表,并且它只能是大于0的整数。
mtext是消息数据本身。
mtext字段不但可以存储字符,还可以存储任何其他的数据类型。此字段可以说是完全任意的,因为程序员自己可以重新定义此数据结构。请看下面重新定义的例子:
struct my_msgbuf{ long mtype; /*Message type*/ char request_id; /*Request identifier*/ struct client info; /*Client information structure*/ };
这里的消息类型字段和前面的一样,但数据结构的其余部分则由其他的两个字段所代替,而其中的一个还是另外一个结构。这就体现了消息队列的灵活之处。内核本身并不对消息结构中的数据做任何翻译。你可以在其中发送任何信息,但存在一个内部给定的消息大小的限制。在Linux系统中,消息的最大的长度是4056个字节,其中包括mtype,它占用4个字节的长度。
三、创建消息队列 msgget()
int msgget(key_t key, int msgflg);
系统调用msgget()中的第一个参数是消息队列关键字值,可以由ftok()获得。第二个参数msgflg是一些标志,包括:
IPC_CREAT:如果内核中没有此队列,则创建它。
IPC_EXCL:当和IPC_CREAT一起使用时,如果队列已经存在,则返回错误。
当msgget()执行成功时,返回消息队列的标识符,否则返回-1,通过errno和perror()函数查看错误信息.
下面是一个打开和创建一个消息队列的例子,函数返回消息队列的标识符
int open_ queue(key_ t keyval) { int qid; if((qid = msgget(keyval,IPC_CREAT|0660)) == -1){ perror(”msgget”); return(-1); } return(qid); }
发送和接收消息 msgsnd()
当得到了消息队列标识符,就可以在队列上执行发送或者接收消息了。msgsnd()系统调用用于向队列发送一条消息,其函数原型是:
int msgsnd(int msqid, struct msgbuf *msgp, sizet msgsz, int msgflg);
第一个参数是消息队列标识符。
第二个参数msgp,是指向消息缓冲区的指针。
参数msgsz指定了消息的字节大小,但不包括消息类型的长度(4个字节)。
参数msgflg可以设置为:
0:此时为忽略此参数,如果消息队列已满,调用进程将会挂起,直到消息可以写入到队列中。
IPC_NOWAIT:如果消息队列己满,那么此消息则不会写入到消息队列中,控制将返回到调用进程中。消息队列写入成功时,函数返回0,否则返回-1。
int send_message(int qid, struct mymsgbuf *qbuf) { int result, length; /*The length is essentially the size of the structure minus sizeof(mtype)*/ length = sizeof(struct mymsgbuf) - sizeof(long); if((result = msgsnd(qid, qbuf, length, O)) == -1){ perror(”msgsnd”); return(-1); } return(result); }
msgrcv()系统调用用于从消息队列读取一条消息,其函数原型是:
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtype, int msgflg);
第一个参数是消息队列的标识符。
第二个参数代表要存储消息的缓冲区的地址。
第三参数是消息缓冲区的长度,不包括mtype的长度,它可以按照如下的方法计算:
msgsz=sizeof(struct mymsgbuf)-sizeof(long);
第四个参数是要从消息队列中读取的消息的类型。
如果msgtype=0,接收消息队列的第一个消息。大于0接收队列中消息类型等于这个值的第一个消息。小于0接收消息队列中小于或者等于msgtype绝对值的所有消息中的最小一个消息。一般为0。
第五个参数msgflg取值为:
0:从队列中取出最长时间的一条消息。
IPC_NOWAIT:当队列没有消息时,调用会立即返回ENOMSG错误。否则,调用进程将会挂起,直到队列中的一条消息满足msgrcv()的参数要求。
当函数成功时,返回写入缓冲区的数据大小,否则返回-1。
下面是一个接收消息的例子:
来源:https://www.cnblogs.com/hkyst/p/7680901.html