我如何找到 readers/writers 等待 Linux 系统 V 消息队列?

How do I find waiting readers/writers for Linux System V Msg Queues?

我的任务是将一些使用 System V 队列的 C/C++ 代码从 HP-UX 移植到 Red Hat Linux (SVr4)。

大多数调用都很好地翻译了,但我在解决一个特定问题时遇到了困难,因为它涉及到在给定队列中发现等待的读者和作者。

在 HP 上,可以使用 msgctl(IPC_STAT) 获取包含给定队列详细信息的 msqid_ds 结构。

在这个结构的细节中有一个短值 msqid_ds.msg_perm.mode,它使用低 9 位来指定 user/group/others 的 r/w 权限。

然而,在 HP 上,高 7 位存储其他状态信息,其中包括以下两个标志的标志:

#define MSG_QWAIT       00001   /* a writer is waiting on qp->msg_cbytes */
#define MSG_FWAIT       00002   /* a writer is waiting on msgfp */

这允许我们进行测试,例如,(msqid.msg_perm.mode & (MSG_RWAIT | MSG_WWAIT)) 以查看队列中是否有读取器或写入器被阻塞。

当我移植到 Linux 时,很明显这个功能是不一样的。这些标志的定义不存在,msqid_ds.msg_perm.mode 的值显然不存在更高位信息。

但肯定有维护这些队列的读写器的内核操作。我希望可以调用一些操作来发现这些信息。

据我所知,Linux 没有面向用户的工具来获取您想要的信息。 POSIX 也没有定义任何此类设施(甚至对于 POSIX 消息队列也是如此)。当然,内核必须维护消息队列状态是对的,但我看不到可以从用户空间查询该信息的现有机制。除非您喜欢为内核编写驱动程序,否则我认为您的端口将需要进行比您希望的更深层次的更改。

但从长远来看,这不一定是坏事 运行。调整您的代码,使其仅依赖于标准设施,而不是供应商扩展,预计可以使其更健壮、更易于维护和更便携。根据遗留代码试图做的事情,您甚至可能最终在受影响的区域得到一个完全更好的设计。

例如,考虑程序为何需要相关信息,以及它将如何处理这些信息。我只看到一个很好的理由:测试是由进程/线程执行的,作为压力释放机制的一部分,其中如果队列被太多/太大的消息阻塞,一些消息就会被丢弃。我考虑过的所有其他原因要么考虑不周,要么通过使用非阻塞发送和/或接收得到更好的服务。如果你的程序的原因属于后一组,那么它有更好的方法来做它想做的事情。

即使目的是上述压力释放,也请注意,您获得的有关消息队列瞬时状态的任何信息都可能在程序获得之前就已经过时了。在您的程序根据收集到的信息采取行动之前,所有被阻止的发件人可能已经成功处理,并且新的消息发送尝试可能已被阻止。这也许是一个可以理解的约束,但它应该为您的减压策略提供信息。在这种情况下,您至少有以下选择:

  • 与其尝试确定是否有任何发件人被阻止,不如确定队列是否已满。您可以根据标准 struct msqid_ds 确定排队消息的当前数量和最大数量。您还可以确定队列可以容纳的最大字节数,但没有标准方法来确定当前排队的字节数。 (但是,如果您仍然迷恋供应商扩展,则有一种 Linux 特定的方法。)

  • 通过尝试向队列发送消息(使用非阻塞发送)来检查队列是否被阻塞。成功后,立即再次删除该消息。您可以使用消息类型将这些消息与应用程序的其他消息区分开来。在其他接收者的一些合作下,您可以使用消息类型来确保没有其他接收者接收到这些探测消息。