【问题标题】:IPC msgsnd waits unexpectedlyIPC msgsnd 意外等待
【发布时间】: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)修改此限制。)"

标签: linux perl ipc


【解决方案1】:

问题在于队列的默认最大大小内核设置被设置为一个较低的值。

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

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

【讨论】:

    猜你喜欢
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2018-04-08
    • 1970-01-01
    • 2016-11-04
    • 2013-09-29
    相关资源
    最近更新 更多