IPC msgsnd 意外等待

IPC msgsnd waits unexpectedly

[虽然我在 perl 工作,但我相信这个问题与 Linux System V IPC 有关 API 和限制而不是任何东西 perl-specific.]

我有两台 Centos 机器,每台都是 CentOS Linux 7.9.2009 版(核心)。

我有一个程序分叉 child,然后使用 System V IPC 消息与 child 通信,child 准备答案并将它们发送到 parent.

在一台机器上,我们看到了预期的行为。 child 生成消息批次,parent 消耗它们。有时 child 的工作速度比 parent 快一点,因此可能会填满队列,child 然后等待 parent 消耗一些消息并继续。

我们可以使用 ipcs -q 检查队列大小,发现偶尔会达到每个队列 10 条消息的默认限制,child 暂停,然后我们看到队列如预期的那样为空。

我们认为队列限制在 /proc/sys/fs/mqueue/ 中的文件中指定,例如 msg_max被认为是预期的 10。这些值在两台机器上是相同的。

我们还可以使用 ulimit -q 查看与队列相关的用户 ulimits,并在两台机器上看到超过 800,000 字节的值。

令人困惑的是,在我们的第二台机器上,我们看到 child 将三条消息写入队列并尝试写入第四条消息并等待 - 我们故意不设置超时。 就好像作者认为队列已满,即使 ipcs -q 显示队列中只有 3 个项目。此时 parent 尚未尝试读取消息。

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x0000002a 1474560    dave      600        15020        3  

问题:除了队列已满,还有什么会导致 msgsnd() 暂停? 暂停似乎无限期地继续,child 在 parent 时继续 变得活跃并阅读一些消息。

我们有很多机器运行这段代码没有问题。它在三台新机器上失败。 大概有一些 environment-specific 功能与我们的代码交互?

perl 代码在系统调用之上使用了一个精简库(省略了详细信息)

$mQueue = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR | S_IWUSR);
msgsnd( $mQueue, pack("l! a*", length($msg), $msg);

问题是队列的默认最大大小 内核设置设置为较低的值。

可以使用 ipcs 的 -l 选项查看此校准。

ipcs -q -l

------ Messages Limits --------
max queues system wide = 3671
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384

有问题的内核设置存储在

/proc/sys/kernel/msgmnb

并且可以使用命令

更改(作为 root)
 sysctl -w kernel.msgmnb=65536
 kernel.msgmnb = 65536