[英]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.