mq_open() - 打开的文件太多

abu*_*rak 5 c linux posix message-queue

我正在尝试编写一个客户端和服务器,它们将使用 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;
    }
Run Code Online (Sandbox Code Playgroud)

...

服务器:

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);
Run Code Online (Sandbox Code Playgroud)

...

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

Man*_*lva 4

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

cat /proc/sys/fs/file-max
Run Code Online (Sandbox Code Playgroud)

显示系统允许的最大文件描述符数。您可以尝试通过以下方式增加当前正在运行的会话的该值:

sysctl fs.file-max = new_value
Run Code Online (Sandbox Code Playgroud)

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

fs.file-max = new_value
Run Code Online (Sandbox Code Playgroud)

为了确保您达到这个限制,您可以运行

cat /proc/sys/fs/file-nr
Run Code Online (Sandbox Code Playgroud)

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

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

/proc/sys/fs/mqueue/queues_max
Run Code Online (Sandbox Code Playgroud)

获取当前值和

sysctl fs.mqueue.queues_max = new_value
Run Code Online (Sandbox Code Playgroud)

改变它。