我有一个进程通过msgsnd
的消息队列发送数据。另一个使用msgrcv
从队列中读取的进程。读取过程需要等到它有所有消息才能继续。如何判断所有消息是否已发送?
我一直在做的方式是在发送方发送了所有消息之后,然后在while循环中检查队列中的消息数。当没有更多消息时,它会关闭队列。
告诉阅读过程继续做其他事情。但这似乎不太可靠。许多时候发送过程将陷入无限循环检查队列状态。
我有没有办法发送EOF信息并让阅读过程注意到这一点?然后我可以发送EOF并让发送进程退出。
答案 0 :(得分:2)
通常,接收方会注意到发送方已完成发送,因为它尝试接收下一条消息,接收呼叫表明没有任何内容可以接收。通过文件描述符(管道,套接字)进行通信,关闭是“发送EOF”的方式,read
调用返回0字节。对于消息队列,它有点不同,因为它们是基于消息而不是流,并且通常有多个发送者。
您可以使用IPC_RMID
命令调用msgctl
。这会导致对msgrcv
(或msgsnd
)的任何等待或后续调用在某些BSD系统上返回-EIDRM
(-EINVAL
)。这种方法的问题在于队列中可能有待处理的消息尚未读取,因此我们将丢失。
相反,当发件人没有别的东西时,让它向队列发送一条消息,说“我已经完成了”。在接收器中,当您收到此消息时,请删除队列。当您在一个进程的线程之间使用队列时,这很有效。如果有多个进程,则发送方可能会在没有发送终止消息的情况下死亡。
如何处理多进程案例取决于应用程序的结构,特别是当发件人死亡时阅读过程想要做什么。您可以检测到这种情况的一种方法是在发送方和接收方之间设置管道。让接收器上的线程听取管道;如果它检测到文件的结尾,它可以
msgrcv
; msgctl
与IPC_STAT
); msg_qnum == 0
),请将其删除。