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
表
示对消息队列进行查看或删除,这些命令还可以对信号量和共享内存进行管理。