打开文件问题 - 打开的文件太多

4

我有一个运行在Win XP上的多线程应用程序。在某个阶段,其中一个线程使用fopen函数无法打开现有文件。_get_errno函数返回EMFILE,意味着文件打开过多,没有更多的文件描述符可用。我的平台FOPEN_MAX为20。_getmaxstdio返回512。我使用WinDbg进行了检查,发现大约有100个文件是打开状态:

788 Handles
Type            Count
Event           201
Section         12
File            101
Port            3
Directory       3
Mutant          32
WindowStation   2
Semaphore       351
Key             12
Thread          63
Desktop         1
IoCompletion    6
KeyedEvent      1

fopen失败的原因是什么?


编辑:

我编写了一个简单的单线程测试应用程序。这个应用程序可以打开510个文件。我不明白为什么这个应用程序可以打开更多的文件,而多线程应用程序不能。这可能是由于文件句柄泄漏吗?

#include <cstdio> 
#include <cassert> 
#include <cerrno> 
void main() 
{ 
    int counter(0); 

    while (true) 
    { 
        char buffer[256] = {0}; 
        sprintf(buffer, "C:\\temp\\abc\\abc%d.txt", counter++); 
        FILE* hFile = fopen(buffer, "wb+"); 
        if (0 == hFile) 
        { 
            // check error code 
            int err(0); 
            errno_t ret = _get_errno(&err); 
            assert(0 == ret); 
            int maxAllowed = _getmaxstdio(); 
            assert(hFile); 
        } 
    } 
}

也许Windows每个进程有512个描述符的限制(减去stdinstdout的2个)。也许使用线程也会消耗一些描述符。目前为止,我只能猜测。我远非Windows内核专家。 - ereOn
您可以编辑问题,无需将源代码写入评论 - codymanix
2个回答

5
我猜这可能是你的操作系统的限制,这取决于很多因素:文件描述符的表示方式、它们占用的内存等等。
我想你无法做太多事情。也许有一些参数可以调整这个限制。
真正的问题是,你确实需要同时打开那么多文件吗?我的意思是,即使你有100个以上的线程试图读取100多个不同的文件,它们可能不会同时读取它们,并且你可能不会比使用50个线程得到更好的结果。
由于我们不知道你想要实现什么目标,所以很难给出更精确的答复。

在开始进行系统优化之前,我想了解问题的原因以及为什么最大打开文件数不是恒定的(在95和103之间变化)。还有哪些因素会影响这一点,例如事件、信号量或目录句柄? - tommyk
@tommyk:这只是一个猜测,我对你的操作系统没有深入的了解(主要是因为你没有说你是在Windows、Linux还是其他什么系统上:D)。我假设在某些系统下,文件描述符是全局的,因此可用描述符(套接字、文件、互斥锁等)的计数受到其他进程和操作系统本身的限制。 - ereOn
我的平台是Windows XP(32位)。 - tommyk

2
我认为在Win32中,所有的CRT函数最终都会使用Win32 API。因此,在这种情况下,最可能使用的是Win32的CreateFile/OpenFile函数。现在,CreateFile/OpenFile API不仅仅用于文件(文件、目录、通信端口、管道、邮件槽、驱动器卷等等)。因此,在实际应用程序中,根据您打开的这些资源数量,您的最大打开文件数可能会有所不同。由于您没有描述应用程序的详细信息,这是我的第一个猜测。如果时间允许,请参阅此链接:http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接