繁体   English   中英

mq_open() - 打开的文件太多

[英]mq_open() - too many open files

我正在尝试编写一个客户端和服务器,它们将使用 POSIX 消息队列交换数据。 我尝试通过查看我在互联网上看到的示例和课程文档来做到这一点。 但是,我陷入了困境。运行它时,出现“打开的文件太多”错误。 这是我的代码:

客户:

int main( int argc, char *argv[]) {

    //Open its queue, which is client queue
    char cq_name[10];
    sprintf( cq_name, "/cq%i", getpid());
    printf( "Client Queue name: %s\n", cq_name);

    mqd_t cq_id = mq_open( cq_name, O_CREAT | O_RDWR, 0666, NULL);
    if( cq_id == -1) {

            printf( "Error in cq: %s\n", strerror( errno));
            return -1;
    }

    printf( "Name: %s\n", argv[1]);

    //Connect to the server message queue
    mqd_t sq_id = mq_open( argv[1], O_RDWR);

    if( sq_id == -1) {

            printf( "Error in sq: %s\n", strerror( errno));
            return -1;
    }

...

服务器:

int main( int argc, char *argv[]) {

    //The server message queue
    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_curmsgs = 0;

    printf( "Name: %s\n", argv[1]);

    mqd_t id = mq_open( argv[1], O_CREAT | O_RDWR, 0666, NULL);

    //Check the message queue
    if( id == -1) {

            printf( "Error: %s\n", strerror(errno));
    }

    printf( "Check Point 1 - %i\n", id);

...

你能帮我找出问题所在。 提前致谢..

本周我遇到了这个问题 - 我最多只能打开 10 mqs。

我的意图是使用 mqs 将事件通知传递给线程。 就我而言, event_id 只是一个 int。 通过在调用 mq_open 时使用指定非默认属性,如下所示:

char mq_name[128];
sprintf(mq_name, "%s.%d", MQ_NAME, nnid);

struct mq_attr attrib;
attrib.mq_flags = 0;
attrib.mq_maxmsg = 4;
attrib.mq_msgsize = sizeof(int);
attrib.mq_curmsgs = 0;

retval = mq = mq_open(mq_name, O_RDWR | O_CREAT | O_EXCL, 0644, &attrib);

在 mq_open() 失败之前,我现在最多可以打开 256 mqs。

通常,Too Many Open files 意味着您正在尝试打开文件描述符,而您已经打开了系统允许的最大文件数。

cat /proc/sys/fs/file-max

向您显示系统上允许的最大文件描述符数。 您可以尝试为当前正在运行的会话增加此值:

sysctl fs.file-max = new_value

或者通过添加以下行来永久编辑/etc/sysctl.conf

fs.file-max = new_value

要确保此限制是您达到的限制,您可以运行

cat /proc/sys/fs/file-nr

第三列 nnumber 与 file-max 报告的相同。 第一列是已分配的文件句柄数,第二列是未使用但已分配的文件句柄数。 如果用第二个数字减去第一个数字得到第三个数字(或接近第三个数字的数字),您就达到了极限。

正如@nos 在评论中所建议的,在手册页指定的mq_open的精确情况下(*ENOSPC 空间不足, mq_open创建新的消息队列。这可能是因为遇到了 queues_max 限制;请参阅 mq_overview(7) *) 您还需要以同样的方式检查fs.mqueue.queues_max的值

/proc/sys/fs/mqueue/queues_max

获取当前值和

sysctl fs.mqueue.queues_max = new_value

改变它。

您可能会在这里遇到许多限制。

假设您使用的是 Linux:

由于您将 NULL 作为最后一个参数传递给 mq_open,您将获得每个队列的默认消息数和最大消息大小。 这些是从

/proc/sys/fs/mqueue/msg_default

/proc/sys/fs/mqueue/msgsize_default

您可以查看这些限制

cat /proc/sys/fs/mqueue/msg_default

并改变它们

sudo echo myNewLimit > /proc/sys/fs/mqueue/msg_default

可以在系统上创建的消息队列总数也有限制。 这存储在/proc/sys/fs/mqueue/queues_max这些和其他限制的文档在MQ_OVERVIEW(7)

您的进程可以分配给消息队列的内存量也有限制。 每个消息队列的内存至少是 (Num_Messages * Message_Length + 簿记开销)。 此限制的详细说明可在此处获得GETRLIMIT(2)

我建议编写一个小的测试程序来创建多个消息队列来试验这些限制。 还记得在开始使用之前检查队列的存在

ls -l /dev/mqueue/ 

还要记住在程序结束时使用mq_unlink删除您的队列,否则它们会在运行之间持续存在。

每次处理完客户端请求和发送响应后,您都需要在服务器代码中关闭客户端。 像这样的东西。

// close the client
if (mq_close (qd_client) == -1) {
        perror ("Client: mq_close");
        exit (1);
}

这是一个完整的工作服务器示例。

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

#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>

#define SERVER_QUEUE_NAME   "/sp-example-server"
#define QUEUE_PERMISSIONS 0666
#define MAX_MESSAGES 10
#define MAX_MSG_SIZE 8000
#define MSG_BUFFER_SIZE MAX_MSG_SIZE + 10

int main (int argc, char **argv)
{
    mqd_t qd_server, qd_client;   // queue descriptors
    long token_number = 1; // next token to be given to client

    struct mq_attr attr;

    attr.mq_flags = O_RDWR | O_CREAT;
    attr.mq_maxmsg = MAX_MESSAGES;
    attr.mq_msgsize = MAX_MSG_SIZE;
    attr.mq_curmsgs = 0;

    if ((qd_server = mq_open (SERVER_QUEUE_NAME, O_RDWR | O_CREAT, QUEUE_PERMISSIONS, &attr)) == -1) {
        perror ("Server: mq_open (server)");
        exit (1);
    }

    char in_buffer [MSG_BUFFER_SIZE];
    char out_buffer [MSG_BUFFER_SIZE];

    while (1) {     // while 1 starts
        // get the oldest message with highest priority
        if (mq_receive (qd_server, in_buffer, MSG_BUFFER_SIZE, NULL) == -1) {
        perror ("Server: mq_receive");
            exit (1);
        }
            // output message from client
        int iter001;

        printf("Message received from Client is following: \n");
        for (iter001 = 0; iter001 < MSG_BUFFER_SIZE; iter001++)
        {
                printf("%c", in_buffer[iter001]);
        }
        printf("\n");

        printf ("Server: message received.\n");

        // send reply message to client

        if ((qd_client = mq_open (in_buffer, O_RDWR | O_CREAT)) == 1) {
        perror ("Server: Not able to open client queue");
        continue;
        }
        printf("Value of qd_client: \n");
        printf("%d\n", qd_client);
        sprintf (out_buffer, "%s", "hello world!");

        printf("Value of out_buffer: %s", out_buffer);
        if (mq_send (qd_client, out_buffer, strlen (out_buffer), 0) == -1) {
        perror ("Server: Not able to send message to client");
        continue;
        }

        printf ("Server: response sent to client.\n");
        token_number++;

        // close the client
        if (mq_close (qd_client) == -1) {
        perror ("Client: mq_close");
        exit (1);
        }

    }   // while 1 ends
}

您可以尝试以下

    struct rlimit r;
    r.rlim_cur = 99999999;
    r.rlim_max = 99999999;
    if (setrlimit(RLIMIT_MSGQUEUE, &r) == 0)
    {
        printf("set RLIMIT: %d\n", r.rlim_cur);
    }
    else printf("failed to set RLIMIT", strerror(errno));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM