【发布时间】:2021-12-16 07:37:42
【问题描述】:
[虽然我在 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);
【问题讨论】:
-
提示:
pack("l! a*", length($msg), $msg)可以写成pack("l!/a*", $msg) -
由于这些是新机器,这里猜测一些愚蠢的默认值。来自
msgop(2)手册页——“如果队列中可用空间不足,则msgsnd()的默认行为是阻塞,直到空间可用。”前两句为:“(队列容量由消息队列相关数据结构中的msg_qbytes字段定义。在队列创建期间,该字段初始化为MSGMNB字节,但可以使用msgctl(2)修改此限制。)"