如何find我的进程在Linux中打开的文件句柄?

当我们在Unix中执行fork时,打开的文件句柄是inheritance的,如果我们不需要使用它们,我们应该closures它们。 但是,当我们使用库时,可能会打开文件句柄,我们无法访问该句柄。 我们如何检查这些打开的文件句柄?

Solutions Collecting From Web of "如何find我的进程在Linux中打开的文件句柄?"

如果图书馆正在打开你不知道的文件,你怎么知道他们叉后不需要它们? 未引出的句柄是内部库的详细信息,如果库希望它们关闭,它将注册一个atfork()处理程序来关闭它们。 走在后面的一些代码关闭后面的文件句柄会导致微妙的难以调试的问题,因为库会意外地出错,当它试图处理它知道它正确打开,但没有关闭的句柄。

在Linux中你可以检查/proc/<pid>/fd目录 – 对于每个打开的fd,都会有一个名为handle的文件。 我几乎可以肯定这种方式是不可移植的。

另外,你可以使用lsof – 根据man lsof说法,可用于Linux,AIX,FreeBSD和NetBSD。

你可以从shell中完成:

lsof -P -n -p _PID_

PID是你的进程PID。

正如@Louis Gerbarg的回答中提到的那样,库可能期望fork() (它应该是父进程的一个几乎相同的副本fork()的文件句柄保持打开状态。

大多数人所exec()的问题是经常跟在fork()exec() fork() 。 在这里,正确的解决方案是创建句柄的库将它们标记为close-on-exec( FD_CLOEXEC )。

在多线程程序使用的库上,创建文件句柄的库和设置FD_CLOEXEC的库(另一个线程可以在两个操作之间fork()之间存在竞争条件。 为了解决这个问题,在Linux内核中引入了O_CLOEXEC

首先,你并不需要关心很多你不知道的打开的文件描述符。 如果你知道你不会再写信给他们,关闭它们是一个好主意,不会伤害 – 毕竟你只是做了一个fork(),这个fds打开了两次。 但同样,如果你把它们放开,他们也不会打扰你 – 毕竟,你不知道他们,你可能不会随机写给他们。

至于你的第三方库会做什么,这有点夸张。 有些人可能不希望遇到fork()的情况,最终可能会在没有任何同步的情况下意外地从两个进程写入相同的fd。 其他人可能不希望你有关于他们的关闭。 你必须检查。 这就是为什么在库中随机打开一个文件描述符并且不给调用者进行管理是一个坏主意。

总之,本着回答原来问题的精神,没有一个特别好的办法。 您可以在文件描述符上调用dup()dup2() 。 如果关闭,通话将失败, EBADF 。 所以你可以说:

 int newfd = dup(oldfd); if (newfd > 0) { close(newfd); close(oldfd); } 

但在这一点上,你最好还是先说close(oldfd) ,然后忽略任何EBADF。

假设你仍然想要关闭所有的核选项,那么你需要找到打开的文件描述符的最大数量。 假设1到65535不是一个好主意。 首先,fds从0开始,当然也没有特定的上限。 为了便于携带,POSIX的sysconf(_SC_OPEN_MAX)应该在任何理智的POSIX系统上告诉你,尽管严格来说这是可选的。 如果你感到偏执,请检查返回值为-1,但是在这一点上,你大多不得不退回硬编码的值(1024应该没问题,除非你做了非常奇怪的事情)。 或者,如果你对Linux特有的很好,你可以在/ proc中进行挖掘。

不要忘记关闭0,1和2 – 这可以真正混淆的东西。

我同意其他人所说的关于随机文件是危险的。 您最终可能会为您的所有第三方工具提交一些非常有趣的错误报告。

也就是说,如果你知道你不需要打开这些文件,你可以遍历所有有效的文件描述符(1到65535,IIRC)并关闭所有你不认识的东西。

合理的库总是具有释放他们分配的任何资源(例如文件句柄)的功能。

只是一个链接,但它似乎有帮助: 多少打开的文件? 在netadmintools.com。 它似乎使用/ proc调查了解一个进程的打开文件,不知道这是唯一的方式,或者如果有一个API。 解析这种类型的信息文件可能有点…凌乱。 另外,/ proc也可能被弃用,需要检查。

这不是一个设计问题吗? 在初始化打开这些文件的库之前,你的进程是否可以fork?