2016-10-31 12 views
8

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

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

#!/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 MQS, прежде чем сообщать OSError: This process already has the maximum number of files open

Я посмотрел в пределах мэк и 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 открытых в одно время. Реально я хочу иметь несколько сотен, может быть, тысячу открытых одновременно.

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

EDIT: Лучшая проверка ошибок в версии C. Еще больше.

+2

Программа C проверка ошибок неверен - проверьте _errno_, если '' mq_open' возвращает (mqd_t) -1' , – pilcrow

+0

@pilcrow Исправлено: –

ответ

5

Параметр 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 

, где атр является 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); 
+0

Ничего из этого не было в то время –