mq_open()——打开的文件太多了

时间:2021-09-18 19:35:18

I'm trying to write a client and server which are going to exchange data by using POSIX message queue. I tried to do it by looking at the examples I saw in the Internet and the documents of the course. But, I am stuck in. When I run it, I get "Too many open files" error. Here is my code:

我正在尝试编写一个客户机和服务器,它们将使用POSIX消息队列交换数据。我试着通过看我在网上看到的例子和课程的文档来做。但是,我被困住了。当我运行它时,我得到“太多打开的文件”错误。这是我的代码:

Client:

客户:

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;
    }

...

Server:

服务器:

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);

...

Can you help me to figure out what the problem is. Thanks in advance..

你能帮我找出问题所在吗?提前谢谢. .

3 个解决方案

#1


2  

I hit this problem this week - that I could only open a max of 10 mqs.

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

My intent is to use mqs to pass notification of events to threads. In my case an event_id is just an int. By using specifying non-default attributes in the call to mq_open like so:

我的意图是使用mqs将事件通知传递给线程。在我的例子中,event_id只是一个int类型。

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);

I am now able to open up to 256 mqs before mq_open() fails.

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

#2


1  

Usually, Too Many Open files means that your are trying to open file descriptors while you already opened the maximum number of files allowed by the system.

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

cat /proc/sys/fs/file-max

show you the maximum number of file descriptors allowed on your system. You can try to increase this value for your current running session with:

显示系统中允许的文件描述符的最大数量。您可以尝试为您当前的运行会话增加这个值:

sysctl fs.file-max = new_value

or permanently by editing /etc/sysctl.conf by adding the following line:

或者通过编辑/etc/sysctl通过增加以下一行:

fs.file-max = new_value

To be sure that this limit is the one you are reaching you can run

确保这个极限是你能达到的极限

cat /proc/sys/fs/file-nr

The third column nnumber is the same as the one reported by file-max. The first column is the number of allocated file handles and the second one is the number of unused but allocated file handles. If substracting of the first number by the second one gives you the third one (or a number close to the third one) you are reaching the limit.

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

As suggested by @nos in a comment, in the precise case of mq_open as specified by the man page (*ENOSPC Insufficient space for the creation of a new message queue. This probably occurred because the queues_max limit was encountered; see mq_overview(7)*) you 'll need also to check in the same way the value of fs.mqueue.queues_max

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

/proc/sys/fs/mqueue/queues_max

to get current value and

获取当前值

sysctl fs.mqueue.queues_max = new_value

to change it.

去改变它。

#3


0  

You need to close the your client in server code every time you are done processing client request and sending response. Something like this.

每次处理客户端请求和发送响应时,都需要在服务器代码中关闭客户端。是这样的。

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

Here's a complete working server example.

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

#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
}

#1


2  

I hit this problem this week - that I could only open a max of 10 mqs.

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

My intent is to use mqs to pass notification of events to threads. In my case an event_id is just an int. By using specifying non-default attributes in the call to mq_open like so:

我的意图是使用mqs将事件通知传递给线程。在我的例子中,event_id只是一个int类型。

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);

I am now able to open up to 256 mqs before mq_open() fails.

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

#2


1  

Usually, Too Many Open files means that your are trying to open file descriptors while you already opened the maximum number of files allowed by the system.

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

cat /proc/sys/fs/file-max

show you the maximum number of file descriptors allowed on your system. You can try to increase this value for your current running session with:

显示系统中允许的文件描述符的最大数量。您可以尝试为您当前的运行会话增加这个值:

sysctl fs.file-max = new_value

or permanently by editing /etc/sysctl.conf by adding the following line:

或者通过编辑/etc/sysctl通过增加以下一行:

fs.file-max = new_value

To be sure that this limit is the one you are reaching you can run

确保这个极限是你能达到的极限

cat /proc/sys/fs/file-nr

The third column nnumber is the same as the one reported by file-max. The first column is the number of allocated file handles and the second one is the number of unused but allocated file handles. If substracting of the first number by the second one gives you the third one (or a number close to the third one) you are reaching the limit.

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

As suggested by @nos in a comment, in the precise case of mq_open as specified by the man page (*ENOSPC Insufficient space for the creation of a new message queue. This probably occurred because the queues_max limit was encountered; see mq_overview(7)*) you 'll need also to check in the same way the value of fs.mqueue.queues_max

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

/proc/sys/fs/mqueue/queues_max

to get current value and

获取当前值

sysctl fs.mqueue.queues_max = new_value

to change it.

去改变它。

#3


0  

You need to close the your client in server code every time you are done processing client request and sending response. Something like this.

每次处理客户端请求和发送响应时,都需要在服务器代码中关闭客户端。是这样的。

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

Here's a complete working server example.

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

#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
}