c - 为什么在 POSIX 中创建消息队列时出现错误 "Cannot Allocate Memory"?

标签 c linux posix ipc message-queue

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

最佳答案

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

首先,要了解RLIMIT_MSGQUEUE 资源限制,请参阅man setrlimit 中的公式:

RLIMIT_MSGQUEUE (Since Linux 2.6.8) Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process. This limit is enforced for mq_open(3). Each message queue that the user creates counts (until it is removed) against this limit according to the formula:

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

where attr is the mq_attr structure specified as the fourth argument to mq_open(3). The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures that the user cannot create an unlimited number of zero-length messages (such messages nevertheless each consume some system memory for bookkeeping overhead).

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

要将 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 硬限制的约束下,也可以摆脱几百个队列。当然,这取决于您的特定用例。

如果您有系统的根访问权限,调整RLIMIT_MSGQUEUE 硬限制并不困难。一旦您确定了限制应该是多少,请在 /etc/security/limits.conf 中调整系统范围的设置。例如,要为 www-data 用户组设置 4 兆字节的硬限制和软限制,并且对 super 用户没有限制,您需要将以下行添加到文件中:

@www-data   -   msgqueue    4194304
root        -   msgqueue    unlimited

关于c - 为什么在 POSIX 中创建消息队列时出现错误 "Cannot Allocate Memory"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5285101/

相关文章:

linux - 在 linux(或 POSIX)中类似于 win32 mem api 的功能

c - 接受系统调用时出现段错误

c++ - for if语句,虽然为true,但是又循环了

c - 通过 TCP 连接发送格式化消息

c - 为什么数字c程序的逆序是用数字位置的概念编写的,而不是像下面我发布的那样?

Linux 读入一个数组

linux - 在 Ubuntu 中备份整个磁盘

linux - for 循环中 if 语句中的 if 语句

根据变量的值更改 printf() 中的文本

c - pthread 互斥体在等待时未解锁