【问题标题】:Why is there a error "Cannot Allocate Memory" while creating message queue in POSIX?为什么在 POSIX 中创建消息队列时出现“无法分配内存”错误?
【发布时间】:2011-07-14 04:40:23
【问题描述】:

为什么在 POSIX 中创建消息队列时出现“无法分配内存”错误?

【问题讨论】:

  • 您使用什么代码来尝试创建它?
  • 猜想,但是当您创建消息队列时,您的系统可能无法分配足够的内存(也许您在创建队列时传递了一些错误的参数,请显示该代码)

标签: c linux posix ipc message-queue


【解决方案1】:

Adrian 的回答是正确的,但由于这是在 Linux 上首次尝试将 POSIX 消息队列用于任何重要的事情时遇到的一个令人沮丧的常见错误,我想我会添加一些有用的细节。

首先要了解RLIMIT_MSGQUEUE的资源限制,见man setrlimit处的公式:

RLIMIT_MSGQUEUE(自 Linux 2.6.8 起) 指定可以为调用进程的真实用户 ID 的 POSIX 消息队列分配的字节数限制。对 mq_open(3) 强制执行此限制。用户创建的每个消息队列都会根据以下公式计算(直到被删除):

bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +
        attr.mq_maxmsg * attr.mq_msgsize

其中 attr 是指定为 mq_open(3) 的第四个参数的 mq_attr 结构。 公式中的第一个加数包括 sizeof(struct msg_msg *)(在 Linux/i386 上为 4 个字节),确保用户不能创建无限数量的零长度消息(尽管这样的消息每个都消耗一些系统内存来记账开销)。

鉴于 Linux 上的默认 MQ 设置(mq_maxmsg = 10、mq_msgsize = 8192),对于 819200 字节的默认限制,上述公式仅适用于大约 10 个消息队列。因此,为什么你会遇到这个问题,例如完成后忘记关闭和取消链接几个队列。

要将RLIMIT_MSGQUEUE 资源限制提高到用户允许的最大值,您可以在应用程序的启动代码中使用类似以下内容:

#ifdef __linux__
    // Attempt to raise the resource limits for POSIX message queues to
    // the current hard limit enforced for the current real user ID:
    struct rlimit rlim = {RLIM_INFINITY, RLIM_INFINITY};
    const int rc = getrlimit(RLIMIT_MSGQUEUE, &rlim);
    if (rc == 0 && rlim.rlim_cur != rlim.rlim_max) {
      rlim.rlim_cur = rlim.rlim_max;
      setrlimit(RLIMIT_MSGQUEUE, &rlim);
    }
#endif

如果您还确保在打开队列时将mq_maxmsgmq_msgsize 属性设置为较低的值(请参阅man mq_open),即使在限制范围内,您也可以避免数百个队列默认RLIMIT_MSGQUEUE 硬限制。当然,这取决于您的特定用例。

如果您对系统具有 root 访问权限,则调整 RLIMIT_MSGQUEUE 硬限制并不困难。一旦你弄清楚了应该是什么限制,在/etc/security/limits.conf 中调整系统范围的设置。例如,要为 www-data 用户组设置 4 MB 的硬性和软性限制,并且对超级用户没有限制,您可以在文件中添加以下行:

@www-data   -   msgqueue    4194304
root        -   msgqueue    unlimited

【讨论】:

  • 另一个陷阱:注意计算 setrlimit 所需的字节,不仅是一个队列,如果你使用多个队列,还要计算所有队列。
【解决方案2】:

最可能的原因是您请求的消息队列大于允许的空间。系统限制在/proc/sys/fs/mqueue/ 中控制。还有一个每个用户的限制 (RLIMIT_MSGQUEUE),它控制单个用户可以分配的字节总数。要检查系统上的设置,请查看 ulimit -q 的值,默认为 819200 字节。

开发人员认为消息队列适用于小型、低延迟的消息。分发使用较大消息队列的应用程序很困难,因为需要更改系统管理才能解除限制。

【讨论】:

    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 2012-02-11
    • 2014-06-18
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多