2

我有一个进程通过消息队列发送数据msgsnd。另一个进程从队列中读取msgrcv. 读取过程需要等到它拥有所有消息才能继续。我如何告诉它所有消息都已发送?

我一直这样做的方式是在发件人发送完所有消息之后,它会在一个while循环中检查队列中的消息数量。当没有更多消息时,它会关闭队列。

这告诉阅读过程继续做其他事情。不过,这似乎不太可靠。很多时候,发送进程会陷入检查队列状态的无限循环。

有没有办法让我只发送一条 EOF 消息并让阅读过程注意这一点?然后我可以发送 EOF 并退出发送进程。

4

1 回答 1

2

通常接收者会注意到发送者已经完成发送,因为它试图接收下一条消息,并且接收调用表明没有任何东西可以接收。通过文件描述符(管道、套接字)进行通信,关闭文件就是您“发送 EOF”的方式,并且read调用返回 0 字节。对于消息队列,情况略有不同,因为它们是基于消息的而不是流的,并且通常有多个发送者。

您可以msgctl使用命令调用IPC_RMIDmsgrcv这会导致对(or ) 的任何等待或后续调用msgsnd返回-EIDRM-EINVAL在某些 BSD 系统上)。这种方法的问题在于,队列中可能有接收者尚未读取的未决消息,因此我们会丢失。

相反,当发件人无事可做时,让它向队列发送一条消息,上面写着“我完成了”。在接收器中,当您收到此消息时,移除队列。当您在一个进程的线程之间使用队列时,这很有效。如果有多个进程,发送者可能会在没有发送终止消息的情况下死亡。

如何处理多进程情况将取决于您的应用程序的结构,特别是当发送者死亡时读取进程想要做什么。您可以检测到这一点的一种方法是在发送者和接收者之间设置一个管道。在接收器上有一个线程在该管道上监听;如果它检测到文件的结尾,它可以

  1. 设置一个与调用的线程共享的变量msgrcv
  2. 查看队列(msgctlwith IPC_STAT);
  3. 如果队列为空 ( msg_qnum == 0),则将其删除。
于 2014-05-10T14:18:58.887 回答