【问题标题】:Is there a way to send EOF to the process reading a message queue?有没有办法将 EOF 发送到读取消息队列的进程?
【发布时间】:2014-06-28 05:04:08
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我很难确定您要解决的问题。为什么发送者在处理和完成消息时关心?没有什么可以阻止它关闭队列并在完成写入后退出。这些消息仍将存在给读者。这是消息队列的好处之一。
  • 我以为关闭队列会阻塞它?或者至少给读者一个 msgcv 的值-1
  • 一点也不。队列就像一个投递箱。您甚至不需要同时拥有读者和作家。队列是内核持久的,并且消息将一直保留,直到有东西读取它们、删除队列或重新启动操作系统。
  • 啊,谢谢!我对它做了更多的阅读。这很有帮助。

标签: c unix message-queue sysv-ipc


【解决方案1】:

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

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

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

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

  1. 设置一个与调用msgrcv的线程共享的变量;
  2. 查看队列(msgctlIPC_STAT);
  3. 如果队列为空 (msg_qnum == 0),请将其删除。

【讨论】:

  • 我尝试发送最后一条消息,说明没有更多数据,请读者注意。我需要对其进行更多测试,但这似乎到目前为止有效。
猜你喜欢
  • 1970-01-01
  • 2014-03-07
  • 2021-07-01
  • 1970-01-01
  • 2023-03-27
  • 2011-08-20
  • 2021-07-23
  • 2014-11-20
  • 2013-09-25
相关资源
最近更新 更多