2016-10-31 60 views
8

我正在使用一個python模塊來包裝posix實時擴展以獲取MessageQueues。無法創建超過10個mqueue

這是報告OSError: This process already has the maximum number of files open

我看着MQ限制和RLIMIT並檢查它們都設定非常高的前Python代碼

#!/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。例如。

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版本。仍然最大。

+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消息隊列調用進程的實際用戶ID的字節數的限制。這個限制是爲mq_open(3)強制執行的。用戶根據下式針對該限制產生計數(直到它被移除),每個消息隊列:

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

其中attr是指定爲第四個參數mq_open(3)的mq_attr結構。

公式中的第一個加數(包含sizeof(struct msg_msg *)(Linux/i386上的4個字節))確保用戶無法創建無限數量的零長度消息(但這些消息每個消耗一些系統記憶開銷)。

您也可以嘗試讀取值和乘以你需要的東西:

struct rlimit limit; 

getrlimit(RLIMIT_MSGQUEUE, &limit); 
limit.rlim_cur *= 20; 
limit.rlim_max *= 20; 
setrlimit(RLIMIT_MSGQUEUE, &limit); 
+0

沒有這個工作的時候 –