为什么在 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_maxmsg
和 mq_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/