如何从进程内部查找所有打开的文件?
在fork()
之后(exec()
之前)了解这一点似乎很有用。
我知道存在getdtablesize()
和更可移植的sysconf(_SC_OPEN_MAX)
,但尝试关闭每个有效的文件描述符,无论其后面是否有打开的文件,似乎效率低下。(我也意识到了过早优化的危险,但这更多是关乎美观方面的考虑 :-))
如何从进程内部查找所有打开的文件?
在fork()
之后(exec()
之前)了解这一点似乎很有用。
我知道存在getdtablesize()
和更可移植的sysconf(_SC_OPEN_MAX)
,但尝试关闭每个有效的文件描述符,无论其后面是否有打开的文件,似乎效率低下。(我也意识到了过早优化的危险,但这更多是关乎美观方面的考虑 :-))
fork
和exec
,那么你应该使用O_CLOEXEC
标志打开所有文件描述符,这样在exec
之前就不需要手动关闭它们。你也可以使用fcntl
在文件打开后添加此标志,但在多线程程序中会存在竞争条件。尝试关闭所有文件描述符可能听起来效率不高,但实际上并不那么糟糕。如果系统良好,查找文件描述符的系统调用实现应该相当有效。
如果您只想关闭已打开的文件描述符,则可以在存在该文件系统的系统上使用proc文件系统。例如,在Linux上,/proc/self/fd将列出所有打开的文件描述符。遍历该目录,并关闭大于2的所有内容,但要排除表示正在遍历的目录的文件描述符。
在支持的系统上(基本上是除了Linux以外的任何Unix系统),有一个专门为此设计的系统调用closefrom(2)。
刚刚花了几个小时追踪一个错误,关闭所有文件描述符确实可能会导致问题。
问题是,有多少个文件描述符?
1024曾经非常普遍,而且关闭1024个文件句柄并不是完全不合理的。由于大多数文件已关闭,因此这只是在内存中检查一个字节。
我的操作系统默认提供1,048,576个文件描述符。在这个(速度较慢的)服务器上,尝试关闭一个文件句柄显然需要超过4.7微秒。这导致了超时(5秒)。而且也没有人能够预计这个数字会增长到多高。至少要给它设定一个(合理的)上限。
/proc/self/fd并不理想,但像这样的错误非常难以发现。