Ответ Адриана верен, но, поскольку это ошибочно встречающаяся ошибка, с которой приходится сталкиваться в Linux при первой попытке использовать очереди сообщений POSIX для чего-то нетривиального, я решил добавить некоторые полезные сведения.
Во-первых, чтобы понять ограничение ресурса RLIMIT_MSGQUEUE
, см. Формулу в man setrlimit
:
RLIMIT_MSGQUEUE (начиная с Linux 2.6.8)
Указывает ограничение на количество байтов, которые могут быть выделены для очередей сообщений POSIX для реального идентификатора пользователя вызывающего процесса. Это ограничение применяется для mq_open (3). Каждая очередь сообщений, которую создает пользователь, учитывает (до тех пор, пока она не будет удалена) этот предел согласно формуле:
bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +
attr.mq_maxmsg * attr.mq_msgsize
где attr - структура mq_attr, указанная в качестве четвертого аргумента для mq_open (3).
Первое дополнение в формуле, которое включает sizeof (struct msg_msg *) (4 байта в Linux / i386), гарантирует, что пользователь не может создавать неограниченное количество сообщений нулевой длины (такие сообщения, тем не менее, каждый из них использует некоторую системную память для накладных расходов на ведение бухгалтерского учета ).
Учитывая настройки MQ по умолчанию (mq_maxmsg
= 10, mq_msgsize
= 8192) в Linux, приведенная выше формула работает только с 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
не составляет труда, если у вас есть root-доступ к системе. Как только вы выяснили, каким должен быть предел, настройте общесистемные настройки в /etc/security/limits.conf
. Например, чтобы установить жесткий и мягкий лимит в 4 мегабайта для группы пользователей www-data
, а для суперпользователя ограничений нет, добавьте в файл следующие строки:
@www-data - msgqueue 4194304
root - msgqueue unlimited