struct msqid_ds结构体
可以通过命令man msgctl来查看这个结构体的定义。
1  | struct msqid_ds {  | 
msgget()函数
1  | 
  | 
msgget()会返回一个消息队列标识符,发送和接收消息都需要指定标识符。参数key可
以是IPC_PRIVATE或者是由ftok()创建的 IPC key。这个参数似乎也可以手工指定,我
并没有尝试过,但这样可能与系统中已存在的相冲突。
参数msgflg用来在给定一些控制信息,包括创建消息队列(IPC_CREAT)和在创建时设置
权限等。一个小例子:
1  | 
  | 
msgctl()函数
1  | int msgctl(int msqid, int cmd, struct msqid_ds *buf);  | 
参数cmd用来指定要进行的操作,比如IPC_STAT用来得到内核中关于msqid所指定的消
息队列的信息,结果存放在buf中,IPC_SET用来修改内核中此消息队列的一些信息,由buf所指向的结构体保存要修改的内容,但并不是所有的信息都可以修改(uid, gid, mode
可以修改),IPC_RMID用来删除消息队列,删除时如果有进程阻塞在此队列,则会被唤醒
且设置其errno为EIDRM。IPC_RMID的用法类似于 msgctl(msqid, IPC_RMID,
NULL);。下面是一个演示的小程序:
1  | 
  | 
msgsnd()函数
1  | int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);  | 
参数msgp是要传递的消息,由一个结构体定义,这个结构体需要由函数调用者自己定义,
Linux 手册中给出的一个例子为:
1  | struct msgbuf {  | 
可以根据需要自己定义,除了第一个域mtype必须的(且其值必须大于 0),其余不做要
求(包括是否存在及长度),msgsz定义除mtype之外msgbuf的大小。mtype的值可
在msgrcv()函数中指定用来选择消息。
msgsnd()会将msgp指向的消息复制一份追加到指定的消息队列中。如果消息队列中有足
够的空间,msgsnd()会立即返回,如果没有足够的空间,则会阻塞直到有空间可用。也可
以在参数msgflg中加入IPC_NOWAIT,这样便不会阻塞,而是出错返回。
示例如下:
1  | 
  | 
msgrcv()函数
1  | ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,  | 
msgrcv()函数用来从消息队列中移除一条消息,并将移除的消息放在参数msgp中。参数msgtyp用来指定消息类型。msgsz用来指定消息的最大长度(不包括消息中的msgtyp
部分)。如果消息的长度大于msgsz所指定的长度,则函数的行为取决于 msgflg中是否
指定了MSG_NOERROR,如果指定了,消息会被截断(而被截断的部分将会丢失);如果未指定,
则返回-1,消息不会从队列中移除。
关于msgtyp:
- 值为 0 时,队列中第一个消息会被读取;
 - 值大于 0 时,队列中第一个类型为
msgtyp的消息会被读取; - 值小于 0 时,队列中类型值最小且小于
msgtyp绝对值的第一个消息。 
一个简单的例子如下:
1  | 
  | 
注意
消息队列不会在程序退出后自动删除,需要在程序中使用msgctl()进行删除(cmd参数使用IPC_RMID),或者使用命令ipcs -q查看,使用ipcrm -q <id>删除。其中参数-q表
示对消息队列进行查看或删除,这些命令还可以对信号量和共享内存进行管理。