[虽然我在 perl 中工作,但我相信这个问题与 Linux System V IPC API 和限制有关,而不是与 perl 特定的任何东西有关。]
我有两台 Centos 机器,每台都是 CentOS Linux 版本 7.9.2009 (Core)。
我有一个程序,它分叉一个孩子,然后使用 System V IPC 消息与孩子沟通,孩子准备答案并将其发送给父母。
在一台机器上,我们看到了预期的行为。孩子产生一批消息,父母消费它们。有时孩子的工作速度比父母快一点,因此可能会填满队列,然后孩子等待直到父母消费一些消息并继续。
我们可以使用 ipcs -q 检查队列大小,发现偶尔会达到每个队列 10 条消息的默认限制,子进程暂停,然后我们看到队列按预期为空。
我们认为队列限制是在/proc/sys/fs/mqueue/中的文件中指定的,例如msg_max被视为预期的 10。这些值在两台机器上是相同的。
我们还可以使用ulimit -q查看与队列相关的用户ulimit ,并在两台机器上看到超过 800,000 字节的值。
令人困惑的是,在我们的第二台机器上,我们看到孩子将三条消息写入队列并尝试写入第四条并等待——我们故意设置不超时。就好像作者认为队列已满,即使 ipcs -q 仅显示队列中的 3 个项目。此时,父级尚未尝试读取消息。
------ Message Queues --------
key msqid owner perms used-bytes messages
0x0000002a 1474560 dave 600 15020 3
问题:除了队列已满,还有什么会导致 msgsnd() 暂停?暂停似乎无限期地继续,当父母变得活跃并阅读一些消息时,孩子继续。
我们有许多机器运行此代码而没有问题。它在三台新机器上失败。大概有一些特定于环境的功能与我们的代码交互?
perl 代码在系统调用之上使用了一个瘦库(省略了细节)
$mQueue = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR | S_IWUSR);
msgsnd( $mQueue, pack("l! a*", length($msg), $msg);
问题是队列内核设置的默认最大大小设置为低值。
可以使用 ipcs 的 -l 选项查看此文件。
有问题的内核设置存储在
并且可以使用以下命令进行更改(以 root 身份)