是否有可能在linux中打开具有大量元素的消息队列?

awe*_*oon 5 c linux message-queue

根据文档,/proc/sys/fs/mqueue/msg_max可以使用以增加队列中消息的限制.文档还说,限制不应超过HARD_MSGMAX,这是65,536自Linux 3.5以来.

但是,即使使用500个元素尝试打开队列也会失败EMFILE:

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

int main(int argc, char** argv)
{
    int message_size = argc > 1 ? atoi(argv[1]) : 16;
    int queue_size = argc > 2 ? atoi(argv[2]) : 10000;

    printf("Trying to open queue with msgsize: %d, and maxmsg: %d\n", message_size, queue_size);

    struct mq_attr initial_attributes = (struct mq_attr){
            .mq_msgsize = message_size,
            .mq_maxmsg = queue_size
    }; 

    int open_flags = O_RDWR | O_CREAT | O_EXCL;
    int permissions = S_IWUSR | S_IRUSR;

    const char* name = "/message_queue_name;";
    mqd_t queue = mq_open(name, open_flags, permissions, &initial_attributes);

    if(queue == -1)
    {
        printf("Cannot open message queue\n");
        printf("Errno: %d [%s]\n", errno, strerror(errno));
        return 1;
    }
    else
    {
        printf("Queue has been opened successfully. Closing...\n");
        mq_close(queue);
        mq_unlink(name);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

测试:

$ cat /proc/sys/fs/mqueue/msg_max
65536

$ ./main 16 300
Trying to open queue with msgsize: 16, and maxmsg: 300
Queue has been opened successfully. Closing...

$ ./main 16 500
Trying to open queue with msgsize: 16, and maxmsg: 500
Cannot open message queue
Errno: 24 [Too many open files]
Run Code Online (Sandbox Code Playgroud)

根据文档,EMFILE错误代码意味着,该进程已经打开了最大数量的文件和消息队列,但该程序不会打开任何其他文件.

所以,我的问题是:如何打开具有大量元素的消息队列?


UPD [1]

这是我的系统限制:

$ ulimit -a
-t: cpu time (seconds)              unlimited
-f: file size (blocks)              unlimited
-d: data seg size (kbytes)          unlimited
-s: stack size (kbytes)             8192
-c: core file size (blocks)         0
-m: resident set size (kbytes)      unlimited
-u: processes                       62820
-n: file descriptors                1024
-l: locked-in-memory size (kbytes)  unlimited
-v: address space (kbytes)          unlimited
-x: file locks                      unlimited
-i: pending signals                 62820
-q: bytes in POSIX msg queues       819200
-e: max nice                        30
-r: max rt priority                 99
-N 15:                              unlimited
Run Code Online (Sandbox Code Playgroud)

gav*_*avv 7

您遇到了RLIMIT_MSGQUEUE限制,请参阅mq_overview(7):

资源限制

RLIMIT_MSGQUEUE资源限制,这对可通过所有属于一个进程的实际用户ID的消息队列被占用的空间量的限制,在被描述getrlimit(2).

在呼叫之前增加它mq_open(),例如:

...
#include <sys/resource.h>

int main(int argc, char** argv)
{
    struct rlimit rlim;
    rlim.rlim_cur = RLIM_INFINITY;
    rlim.rlim_max = RLIM_INFINITY;

    if (setrlimit(RLIMIT_MSGQUEUE, &rlim) == -1) {
        perror("setrlimit");
        return 1;
    }

    ...
Run Code Online (Sandbox Code Playgroud)

您需要root权限(或者CAP_SYS_RESOURCE我认为是功能).


EMFILE对于这种情况,Linux内核真的会返回,请在此处查看:

if (u->mq_bytes + mq_bytes < u->mq_bytes ||
    u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
        spin_unlock(&mq_lock);
        /* mqueue_evict_inode() releases info->messages */
        ret = -EMFILE;
        goto out_inode;
}
Run Code Online (Sandbox Code Playgroud)

EMFILE这里的原因可能是它是POSIX中指定的最接近的错误代码; EMFILE是唯一反映达到每个进程限制的错误代码.

POSIX没有指定更精确的错误代码,RLIMIT_MSGQUEUE因为它是特定于Linux的.