简体   繁体   English

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

[英]How do I find the file handles that my process has opened in Linux?

When we perform a fork in Unix, open file handles are inherited, and if we don't need to use them we should close them. 当我们在Unix中执行fork时,会继承打开的文件句柄,如果我们不需要使用它们,我们应该关闭它们。 However, when we use libraries, file handles may be opened for which we do not have access to the handle. 但是,当我们使用库时,可能会打开文件句柄,我们无法访问该句柄。 How do we check for these open file handles? 我们如何检查这些打开的文件句柄?

In Linux you can check /proc/<pid>/fd directory - for every open fd there will be a file, named as handle. 在Linux中你可以检查/proc/<pid>/fd目录 - 对于每个打开的fd,都会有一个名为handle的文件。 I'm almost sure this way is non-portable. 我几乎可以肯定这种方式是不便携的。

Alternatively you can use lsof - available for Linux, AIX, FreeBSD and NetBSD, according to man lsof . 另外,根据man lsof说法,你可以使用lsof - 可用于Linux,AIX,FreeBSD和NetBSD。

If the libraries are opening files you don't know about, how do you know they don't need them after a fork? 如果库是打开你不知道的文件,你怎么知道他们在fork之后不需要它们? Unexported handles are an internal library detail, if the library wants them closed it will register an atfork() handler to close them. 未导出的句柄是内部库详细信息,如果库希望它们关闭,它将注册一个atfork()处理程序来关闭它们。 Walking around behind some piece of code closing its file handles behind its back will lead to subtle hard to debug problems since the library will error unexpectedly when it attempts to work with a handle it knows it opened correctly, but did not close. 在一些代码后面走动,关闭其背后的文件句柄将导致微妙的难以调试的问题,因为当它试图使用它知道它正确打开但未关闭的句柄时,库会意外地出错。

You can do from a shell: 你可以从shell做:

lsof -P -n -p _PID_

Where PID is your process pid. PID是你的过程pid。

As mentioned on @Louis Gerbarg's answer, the libraries are probably expecting the file handles to be kept open on fork() (which is supposed to be, after all, an almost identical copy of the parent process). 正如在@Louis Gerbarg的回答中所提到的,库可能期望文件句柄在fork()上保持打开fork()毕竟,它应该是父进程的几乎相同的副本)。

The problem most people have is on the exec() which often follows the fork() . 大多数人exec()的问题是exec() ,它经常跟在fork() Here, the correct solution is for the library which created the handles to mark them as close-on-exec ( FD_CLOEXEC ). 这里,正确的解决方案是创建句柄的库,将它们标记为close-on-exec( FD_CLOEXEC )。

On libraries used by multithread programs, there is a race condition between a library creating a file handle and setting FD_CLOEXEC on it (another thread can fork() between both operations). 在多线程程序使用的库上,创建文件句柄的库和在其上设置FD_CLOEXEC之间存在竞争条件(另一个线程可以在两个操作之间fork() )。 To fix that problem, O_CLOEXEC was introduced in the Linux kernel. 为了解决这个问题,在Linux内核中引入了O_CLOEXEC

To start with, you don't really need to care a whole lot about the open file descriptors you don't know about. 首先,您并不需要关心您不了解的打开文件描述符。 If you know you're not going to write to them again, closing them is a good idea and doesn't hurt - you just did a fork() after all, the fds are open twice. 如果你知道你不会再给他们写信,那么关闭他们是一个好主意而且不会受到伤害 - 毕竟你只是做了一个fork(),fds打开了两次。 But likewise, if you leave them open , they won't bother you either - after all, you don't know about them, you presumably won't be randomly writing to them. 但同样地,如果你把它们打开,它们也不会打扰你 - 毕竟,你不了解它们,你可能不会随意写信给它们。

As for what your third-party libraries will do, it's a bit of a toss-up either way. 至于你的第三方图书馆会做什么,无论哪种方式,这都是一个折腾。 Some probably don't expect to run into a situation with a fork(), and might end up accidentally writing to the same fd from two processes without any synchronization. 有些人可能不希望遇到fork()的情况,并且可能最终意外地从两个进程写入相同的fd而没有任何同步。 Others probably don't expect to have you closing their fds on them. 其他人可能不希望你关闭他们的fds。 You'll have to check. 你必须检查。 This is why it's a bad idea to randomly open a file descriptor in a library and not give it to the caller to manage. 这就是为什么在库中随机打开文件描述符而不是将其提供给调用者来管理是个坏主意的原因。

All that said, in the spirit of answering the original question, there isn't a particularly good way. 所有这一切,本着回答原始问题的精神,没有一个特别好的方法。 You can call dup() or dup2() on a file descriptor; 您可以在文件描述符上调用dup()dup2() ; if it's closed, the call will fail with EBADF . 如果它关闭,则调用将因EBADF而失败。 So you can say: 所以你可以说:

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

but at that point you're just as well off saying close(oldfd) in the first place and ignoring any EBADFs. 但在那一点上,你最好先关闭close(oldfd)并忽略任何EBADF。

Assuming you still want to take the nuclear option of closing everything, you then need to find the maximum number of open file descriptors possible. 假设您仍然想要关闭所有内容的核选项,那么您需要找到可能的最大打开文件描述符数。 Assuming 1 to 65,535 is not a good idea. 假设1到65,535不是个好主意。 First of all, fds start at 0, of course, but also there's no particular upper limit defined. 首先,fds当然从0开始,但也没有定义特定的上限。 To be portable, POSIX's sysconf(_SC_OPEN_MAX) should tell you, on any sane POSIX system, though strictly speaking it's optional. 为了便携,POSIX的sysconf(_SC_OPEN_MAX)应该在任何理智的POSIX系统上告诉你,尽管严格来说它是可选的。 If you're feeling paranoid, check the return value for -1, though at that point you mostly have to fall back on a hardcoded value anyway (1024 should be fine unless you're doing something extremely weird). 如果你感觉偏执,请检查-1的返回值,不过在这一点上你大部分都必须依靠硬编码值(1024应该没问题,除非你做的事非常奇怪)。 Or if you're fine with being Linux-specific, you can dig around in /proc. 或者,如果您特定于Linux,那么您可以在/ proc中进行挖掘。

Don't forget to not close fds 0, 1, and 2 - that can really confuse things. 不要忘记不关闭fds 0,1和2 - 这可能会让事情变得混乱。

I agree with what other people have said about closing random files being dangerous. 我同意其他人关于关闭随机文件危险的说法。 You might end up filing some pretty interesting bug reports for all of your third-party tools. 您最终可能会为所有第三方工具提交一些非常有趣的错误报告。

That said, if you know you won't need those files to be open, you can always walk through all of the valid file descriptors (1 to 65535, IIRC) and close everything you don't recognize. 也就是说,如果您知道不需要打开这些文件,您可以随时浏览所有有效的文件描述符(1到65535,IIRC)并关闭所有您无法识别的文件。

合理的库总是具有释放它们已分配的任何资源(例如文件句柄)的函数。

Just a link, but it seems helpful: How many open files? 只是一个链接,但似乎有帮助: 打开多少文件? at netadmintools.com. 在netadmintools.com。 It seems to use /proc investigations to learn about a process' open files, not sure if that is the only way or if there is an API. 它似乎使用/ proc调查来了解进程的打开文件,不确定这是否是唯一的方法或是否有API。 Parsing files for this type of information can be a bit ... messy. 解析此类信息的文件可能有点......凌乱。 Also, /proc might be deprecated too, something to check for. 此外,/ proc也可能已被弃用,需要检查。

Isn't this a design issue ? 这不是一个设计问题吗? Is it possible for your process to fork before initializing the libs that open those files ? 在初始化打开这些文件的库之前,您的进程是否可以进行分叉?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM