我正在使用 Posix 消息队列进行通信的 Suse Linux 上编写客户端/服务器进程,类似于“如何在基于 Linux 的系统上的 ac 程序中使用 mqueue? ”中接受的答案。当服务器死机时,它会执行mq_close和mq_unlink。但是,客户端不会收到此通知,因此即使队列已取消链接,客户端中对mq_send的调用仍将继续工作。
问题是,当服务器重新启动时,它尝试使用 O_CREAT 创建一个带有mq_open的队列,但这会失败,因为客户端仍然有一个打开的 fd。因此,即使 /dev/mqueue 中的文件名似乎不存在,服务器也无法创建一个,直到客户端退出并关闭其文件描述符。我只是想确保我理解正确:如果我希望服务器关闭、取消链接并重新打开 mqueue(例如:具有不同的属性),它肯定需要客户端退出或关闭它的 fd 吗?这与处理普通文件的方式有很大不同:我可以删除另一个进程正在使用的文件,文件系统可能会将其重命名为“.nfsXXX”,他们可以继续使用它,但我可以创建一个新的立即使用该名称的文件。
我第一次尝试解决这个问题只是在服务器退出时不取消链接 mqueue - 如果我想允许重新启动服务器而不需要重新启动客户端,那么我想我不应该取消链接队列(因为服务器知道客户端可能仍在使用 mqueue,它不应该被取消链接)。
理想情况下,我希望新的mq_open在服务器中成功,而下一个mq_send在客户端中失败。有没有一种简单的方法来模拟这个?我想到的方法是:
- 在每次mq_send之前在“/dev/mqueue/queueName”上执行 fstat(或其他东西)(糟糕!),如果名称不存在则关闭 fd(当服务器尝试在循环中重新创建它时),但即便如此如果由于队列已满,客户端当前在mq_send上被阻塞,则无法完美运行。
- 在客户端中有一个单独的套接字,当服务器希望客户端关闭其 mqueue 时,服务器将向该套接字发送消息(并且可能在客户端中有一个单独的线程来监视该套接字)。
- 让服务器杀死客户端。