通常接收者会注意到发送者已经完成发送,因为它试图接收下一条消息,并且接收调用表明没有任何东西可以接收。通过文件描述符(管道、套接字)进行通信,关闭文件就是您“发送 EOF”的方式,并且read
调用返回 0 字节。对于消息队列,情况略有不同,因为它们是基于消息的而不是流的,并且通常有多个发送者。
您可以msgctl
使用命令调用IPC_RMID
。msgrcv
这会导致对(or ) 的任何等待或后续调用msgsnd
返回-EIDRM
(-EINVAL
在某些 BSD 系统上)。这种方法的问题在于,队列中可能有接收者尚未读取的未决消息,因此我们会丢失。
相反,当发件人无事可做时,让它向队列发送一条消息,上面写着“我完成了”。在接收器中,当您收到此消息时,移除队列。当您在一个进程的线程之间使用队列时,这很有效。如果有多个进程,发送者可能会在没有发送终止消息的情况下死亡。
如何处理多进程情况将取决于您的应用程序的结构,特别是当发送者死亡时读取进程想要做什么。您可以检测到这一点的一种方法是在发送者和接收者之间设置一个管道。在接收器上有一个线程在该管道上监听;如果它检测到文件的结尾,它可以
- 设置一个与调用的线程共享的变量
msgrcv
;
- 查看队列(
msgctl
with IPC_STAT
);
- 如果队列为空 (
msg_qnum == 0
),则将其删除。