提问人:oliver 提问时间:9/12/2008 最后编辑:ks1322oliver 更新时间:9/5/2020 访问量:36719
Linux 上的核心转储文件:如何获取有关打开文件的信息?
core dump files on Linux: how to get info on opened files?
问:
我有一个来自可能存在文件描述符泄漏的进程的核心转储文件(它打开文件和套接字,但显然有时会忘记关闭其中一些文件和套接字)。有没有办法找出进程在崩溃之前打开了哪些文件和套接字?我无法轻易重现崩溃,因此分析核心文件似乎是获得有关该错误提示的唯一方法。
答:
核心转储是进程在崩溃时有权访问的内存的副本。根据泄漏的发生方式,它可能已经失去了对手柄的引用,因此它可能被证明是无用的。
LSOF列出了系统中所有当前打开的文件,您可以检查其输出以查找泄漏的套接字或文件。是的,您需要运行该过程。您可以使用特定的用户名运行它,以便轻松辨别哪些是正在调试的进程中打开的文件。
我希望其他人有更好的信息:-)
您可以尝试使用 来查看程序进行的 和调用。strace
open
socket
close
编辑:我不认为你可以从核心中获取信息;它最多会在某处有文件描述符,但这仍然没有给你实际的文件/套接字。(假设您可以区分打开和关闭的文件描述符,我也对此表示怀疑。
找出进程打开了哪些文件的另一种方法 - 同样,仅在运行时 - 是查看 /proc/PID/fd/ ,其中包含指向打开文件的符号链接。
如果程序忘记关闭这些资源,可能是因为发生了以下情况:
fd = open("/tmp/foo",O_CREAT);
//do stuff
fd = open("/tmp/bar",O_CREAT); //Oops, forgot to close(fd)
现在我不会在内存中拥有 foo 的文件描述符。
如果没有发生这种情况,您也许能够找到文件描述符编号,但话又说回来,这并不是很有用,因为它们在不断变化,当您开始调试时,您将不知道它当时的实际含义。
我真的认为你应该用 strace、lsof 和朋友来实时调试它。
如果有办法从核心转储中做到这一点,我也渴望知道:-)
最好的办法是安装一个信号处理程序,用于任何使程序崩溃的信号(SIGSEGV 等)。
然后,在信号处理程序中,检查 /proc/self/fd,并将内容保存到文件中。以下是您可能会看到的内容示例:
Anderson cxc # ls -l /proc/8247/fd
total 0
lrwx------ 1 root root 64 Sep 12 06:05 0 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 1 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 10 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Sep 12 06:05 11 -> socket:[124061]
lrwx------ 1 root root 64 Sep 12 06:05 12 -> socket:[124063]
lrwx------ 1 root root 64 Sep 12 06:05 13 -> socket:[124064]
lrwx------ 1 root root 64 Sep 12 06:05 14 -> /dev/driver0
lr-x------ 1 root root 64 Sep 12 06:05 16 -> /temp/app/whatever.tar.gz
lr-x------ 1 root root 64 Sep 12 06:05 17 -> /dev/urandom
然后,您可以从信号处理程序返回,并且应该像往常一样获得核心转储。
如果你有一个核心文件,并且你已经用调试选项(-g)编译了程序,你可以看到核心被转储到哪里了:
$ gcc -g -o something something.c
$ ./something
Segmentation fault (core dumped)
$ gdb something core
您可以使用它来执行一些事后调试。一些 gdb 命令:bt 打印堆栈,fr 跳转到给定的堆栈帧(参见 bt 的输出)。
现在,如果您想查看哪些文件在分段错误时打开,只需处理 SIGSEGV 信号,然后在处理程序中转储 /proc/PID/fd 目录的内容(即使用 system('ls -l /proc/PID/fs') 或 execv)。
有了这些信息,您可以轻松找到导致崩溃的原因、打开了哪些文件以及崩溃和文件描述符泄漏是否相关。
评论
我跳转到此信息的方法之一是在核心文件上运行。例如,当我最近在核心上运行文件时,由于文件夹的长度,我会得到一个截断的参数列表。我知道我的运行会从我的主目录打开文件,所以我只是运行:strings
strings core.14930|grep jodie
但这是一个我有针和大海捞针的情况。
最近在我的错误故障排除和分析过程中,我的客户为我提供了一个在他的文件系统中生成的核心转储,他离开了工作站,以便快速扫描文件并读取其内容,我使用了该命令
strings core.67545 > coredump.txt 后来我能够在文件编辑器中打开该文件。
评论