第九章第四节 消息队列&其他建议
消息队列
消息队列是在两个进程之间传递二进制块数据的一种简单有效的方式。每个数据块都有一个特定的类型,接收方可以根据类型来有选择地接收数据,而不用像管道那样必须以先进先出的方式接收数据。
msgget系统调用
msgget系统调用创建一个消息队列,或者获取一个已有的消息队列。其定义如下。
1 | /* |
若msgget用于创建消息队列,则与之关联的内核数据结构msqid_ds将被创建并初始化。msqid_ds结构体的定义如下。
1 | /* |
msgsnd系统调用
msgsnd系统调用将一条消息添加到消息队列中;其定义如下。
1 | /* |
msg_ptr必须按照如下格式。
1 | /* |
当消息队列已满,若flg参数指定了IPC_NOWAIT标志时,msgsnd系统调用将立即返回并设置errno为EAGAIN;默认情况下,msgsnd将阻塞。
处于阻塞状态的msgsnd系统调用会被如下两种异常情况中断。
- msqid指定的消息队列被移除,msgsnd函数立即返回并设置errno为EIDRM;
- 调用进程接收到信号,msgsnd函数立即返回并设置errno为EINTR;
msgsnd成功时将修改内核数据结构msqid_ds的部分字段。
- msg_qnum加1;
- 将msg_lspid设置为调用进程的PID;
- 将msg_stime设置为当前时间;
msgrcv系统调用
msgrcv系统调用从消息队列中获取消息,其定义如下。
1 | /* |
处于阻塞状态的msgrcv系统调用会被如下两种异常情况中断。
- msqid指定的消息队列被移除,msgsnd函数立即返回并设置errno为EIDRM;
- 调用进程接收到信号,msgsnd函数立即返回并设置errno为EINTR;
msgsnd成功时将修改内核数据结构msqid_ds的部分字段。
- msg_qnum减1;
- 将msg_lrpid设置为调用进程的PID;
- 将msg_rtime设置为当前时间;
msgctl系统调用
msgctl系统调用控制消息队列的某些属性。其定义如下。
1 | /* |
其他建议
IPC命令
ipcs命令输出系统当前拥有的共享资源实例。ipcrm删除遗留在系统中的共享资源。
进程间传递文件描述符
在之前提到,父进程创建的管道文件描述符在子进程中仍然打开。注意,父进程向子进程传递的并不是一个文件描述符的值,而是在子进程中创建一个新的文件描述符,之后与父进程中的文件描述符指向内核中相同的文件表项。
那么,两个不相关的进程之间,该怎么传递文件描述符呢?示例详见代码清单13-5。