Не может создать более 10 mqueues

Я использую модуль python, который упаковывает расширения реального времени posix для получения MessageQueues.

Это код питона

#!/usr/bin env python
import uuid
import posix_ipc
import time

def spawn():
    return posix_ipc.MessageQueue("/%s" % uuid.uuid4(), flags=posix_ipc.O_CREAT)

i = 0
while True:
    i += 1
    spawn()
    print(i)

Это создаст около 10 мкс перед отчетом OSError: This process already has the maximum number of files open

Я посмотрел на пределы mq и rlimit и проверил, что все они установлены очень высоко. Например

fs.file-max = 2097152
fs.mqueue.msg_max = 1000
fs.mqueue.queues_max = 1000

И даже для привилегированных пользователей все равно будет создано около 10 очередей.

Эквивалент C, использующий расширения реального времени, выглядит следующим образом

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <mqueue.h>

#define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char **argv)
{
    mqd_t mq;
    struct mq_attr attr;
    char buffer[1024 + 1];
    int must_stop = 0;

    /* initialize the queue attributes */
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 1024;
    attr.mq_curmsgs = 0;

    /* create the message queue */
    int count = 0;
    char name[5];
    while (1) {
        sprintf(name, "/%d", count);
        mq = mq_open(name, O_CREAT | O_RDONLY, 0644, &attr);
        if (mq == (mqd_t) -1)
            handle_error("mq_open");
        count++;

    }
    return 0;
}

(скомпилировать с gcc -lrt test.c) Но это только открывает мне 20 mqs за один раз. Реально я хочу иметь несколько сотен, может быть, тысячи открытых одновременно.

У кого-нибудь есть идеи или предложения?

РЕДАКТИРОВАТЬ: Лучшая проверка ошибок в версии C. Все еще макс.

1 ответ

Параметр fs.mqueue.queues_max только глобальное количество очередей сообщений, разрешенных в системе. Достигаемый вами предел - это количество очередей сообщений на процесс. Так как mq_open говорит о кодах ошибок:

[EMFILE] Слишком много дескрипторов очереди сообщений или файловых дескрипторов в настоящее время используются этим процессом.

Обычно вы должны быть в состоянии прочитать (набор), что для каждого процесса предел с getrlimit/ setrlimit, Справочная страница для rlimit говорит:

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), гарантирует, что пользователь не может создавать неограниченное количество сообщений нулевой длины (такие сообщения, тем не менее, каждый из них использует некоторую системную память для накладных расходов на ведение бухгалтерского учета).

Вы также можете попробовать прочитать значение и умножить его на то, что вам нужно:

struct rlimit limit;

getrlimit(RLIMIT_MSGQUEUE, &limit);
limit.rlim_cur *= 20;
limit.rlim_max *= 20;
setrlimit(RLIMIT_MSGQUEUE, &limit);
Другие вопросы по тегам