C++ 如何找到我的进程在 Linux 中打开的文件句柄?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/267825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I find the file handles that my process has opened in Linux?
提问by sep
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. 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?
当我们在 Unix 中执行 fork 时,打开的文件句柄是继承的,如果我们不需要使用它们,我们应该关闭它们。但是,当我们使用库时,可能会打开我们无法访问的文件句柄。我们如何检查这些打开的文件句柄?
回答by qrdl
In Linux you can check /proc/<pid>/fd
directory - for every open fd there will be a file, named as handle. I'm almost sure this way is non-portable.
在 Linux 中,您可以检查/proc/<pid>/fd
目录 - 对于每个打开的 fd,都会有一个名为 handle.txt 的文件。我几乎可以肯定这种方式是不可移植的。
Alternatively you can use lsof
- available for Linux, AIX, FreeBSD and NetBSD, according to man lsof
.
或者,您可以使用lsof
- 可用于 Linux、AIX、FreeBSD 和 NetBSD,根据man lsof
.
回答by Louis Gerbarg
If the libraries are opening files you don't know about, how do you know they don't need them after a fork? Unexported handles are an internal library detail, if the library wants them closed it will register an atfork() handler to close them. 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.
如果库正在打开您不知道的文件,您怎么知道它们在分叉后不需要它们?未导出的句柄是内部库的详细信息,如果库希望它们关闭,它将注册一个 atfork() 处理程序来关闭它们。在一些关闭其背后文件句柄的代码后面走动会导致难以调试的微妙问题,因为当库尝试使用它知道它正确打开但没有关闭的句柄时,它会意外出错。
回答by Louis Gerbarg
You can do from a shell:
您可以从 shell 执行以下操作:
lsof -P -n -p _PID_
lsof -P -n -p _PID_
Where PIDis your process pid.
其中PID是您的进程 pid。
回答by CesarB
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()
(毕竟,这应该是父进程的几乎相同的副本)。
The problem most people have is on the exec()
which often follows the fork()
. Here, the correct solution is for the library which created the handles to mark them as close-on-exec (FD_CLOEXEC
).
大多数人遇到的问题是exec()
经常跟在fork()
. 在这里,正确的解决方案是创建句柄的库将它们标记为 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). To fix that problem, O_CLOEXEC
was introduced in the Linux kernel.
在多线程程序使用的库上,在创建文件句柄和设置文件句柄的库之间存在竞争条件FD_CLOEXEC
(另一个线程可以fork()
在两个操作之间进行)。为了解决这个问题,O_CLOEXEC
Linux 内核中引入了。
回答by C Pirate
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. 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.
首先,您真的不需要非常关心您不知道的打开文件描述符。如果你知道你不会再给他们写信,关闭他们是一个好主意并且不会伤害 - 毕竟你只是做了一个 fork() ,fds 打开了两次。但同样,如果您让它们保持打开状态,它们也不会打扰您——毕竟,您不了解它们,您大概不会随意给它们写信。
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. Others probably don't expect to have you closing their fds on them. 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.
至于你的第三方库会做什么,无论哪种方式都有点折腾。有些人可能不希望遇到 fork() 的情况,最终可能会在没有任何同步的情况下意外地从两个进程写入同一个 fd。其他人可能不希望你关闭他们的 fds。你得检查一下。这就是为什么在库中随机打开文件描述符而不将其交给调用者管理是一个坏主意。
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; if it's closed, the call will fail with EBADF
. So you can say:
综上所述,本着回答原始问题的精神,没有特别好的方法。您可以在文件描述符上调用dup()
或dup2()
;如果它已关闭,则调用将失败并显示EBADF
。所以你可以说:
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. First of all, fds start at 0, of course, but also there's no particular upper limit defined. To be portable, POSIX's sysconf(_SC_OPEN_MAX)
should tell you, on any sane POSIX system, though strictly speaking it's optional. 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). Or if you're fine with being Linux-specific, you can dig around in /proc.
假设您仍然想采取关闭所有内容的核心选项,那么您需要找到可能的最大打开文件描述符数。假设 1 到 65,535 不是一个好主意。首先,fds 当然从 0 开始,但也没有定义特定的上限。为了便于携带,POSIXsysconf(_SC_OPEN_MAX)
应该告诉您,在任何健全的 POSIX 系统上,尽管严格来说它是可选的。如果您感到偏执,请检查 -1 的返回值,尽管此时您通常必须退回到硬编码值(除非您正在做一些非常奇怪的事情,否则 1024 应该没问题)。或者,如果您对特定于 Linux 感到满意,则可以在 /proc 中进行挖掘。
Don't forget to not close fds 0, 1, and 2 - that can really confuse things.
不要忘记不要关闭 fds 0、1 和 2 - 这真的会使事情变得混乱。
回答by Tom Barta
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 knowyou 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)并关闭您不认识的所有内容。
回答by philant
Isn't this a design issue ? Is it possible for your process to fork before initializing the libs that open those files ?
这不是设计问题吗?在初始化打开这些文件的库之前,您的进程是否可以分叉?
回答by Hugh Allen
Reasonable libraries will always have functions which free whatever resources (eg. file handles) they have allocated.
合理的库将始终具有释放它们分配的任何资源(例如文件句柄)的函数。
回答by unwind
Just a link, but it seems helpful: How many open files?at 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. Parsing files for this type of information can be a bit ... messy. Also, /proc might be deprecated too, something to check for.
只是一个链接,但似乎很有帮助:有多少打开的文件?在 netadmintools.com。似乎使用 /proc 调查来了解进程的打开文件,不确定这是唯一的方法还是有 API。解析此类信息的文件可能有点……混乱。此外, /proc 也可能被弃用,需要检查。