找出哪些文件描述符共享相同的“打开文件描述”

找出哪些文件描述符共享相同的“打开文件描述”

如果我这样做(在类似 Bourne 的 shell 中):

exec 3> file 4>&3 5> file 6>> file

文件描述符 3 和 4,因为 4 是dup()从 3 编辑而来,所以共享相同的打开文件描述(相同的属性,文件内相同的偏移量...)。虽然该进程的文件描述符 5 和 6 位于不同的打开文件描述(例如,它们在文件中都有自己的指针)。

现在,在lsof输出中,我们看到的是:

zsh     21519 stephane    3w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG  254,2        0 10505865 /home/stephane/file

用以下方法会好一点lsof +fg

zsh     21519 stephane    3w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG       W,AP,LG  254,2        0 10505865 /home/stephane/file

(在 Linux 3.16 上)我们看到 fd 6 有不同的标志,所以它必须是不同的打开文件描述从 fd 3、4 或 5 上的一个,但从中我们无法看出 fd 5 位于不同的位置打开文件描述。使用-o,我们还可以看到偏移量,但同样的偏移量并不能保证它是相同的打开文件描述

有没有一种非侵入式的方法可以找出答案?外部的,还是进程自己的文件描述符?


1 .一种启发式方法可能是更改一个文件描述符的标志fcntl(),然后查看其他文件描述符的标志因此而更新,但这显然不理想,也不是万无一失的

答案1

对于 Linux 3.5 及更高版本,这可以通过以下方式完成kcmp(2):

KCMP_FILE

  • 检查文件描述符是否存在idx1正在进行中PID1引用相同的打开文件描述(参见打开(2)) 作为文件描述符idx2正在进行中PID2。存在引用相同打开文件描述的两个文件描述符可能是由于以下原因而发生的:重复(2)(和类似的)叉子(2),或通过域套接字传递文件描述符(请参阅UNIX(7))。

手册页提供了一个专门针对 OP 所询问的用例的示例。请注意,此系统调用需要使用 set 来编译内核CONFIG_CHECKPOINT_RESTORE

答案2

您要比较的是struct file文件描述符指向的指针。 (内核内部是task_struct每个线程的一个数据结构。它包含一个指向另一个称为 的结构的指针files_struct。并且结构体包含一个指针数组,每个指针都指向一个struct file.它struct file保存了搜索偏移量、打开标志和一些其他字段。)

files_struct除了使用一些侵入性工具之外,我不知道有任何用户可见的方式来查看指针。例如,可以给 SystemTap 一个 PID,它可以找到相应的 PIDtask_struct并遵循指针。不过,如果你正在寻找被动,我认为仅此而已。戴尔发布了一个工具长的不久前称为 KME(内核内存编辑器),它为实时内核内存提供了一个类似电子表格的界面,它可以做你想做的事情,但它从未移植到 64 位。 (我尝试过,但从未完全正常工作,也不知道为什么。)

您认为没有lsof帮助的原因之一是它也看不到这些指针(但请查看+f非 Linux 系统的选项)。理论上,您可以比较 中的所有字段struct file并认为这两个结构是相同的,但它们仍然可能来自单独的open(2)调用。

看看p文件SystemTap 脚本的想法。如果您修改它以打印 的地址struct file,您就会得到解决方案。您还可以检查按_pid 打开的文件.stp因为其中有一个函数可以遍历files_struct,即。文件描述符表,查看struct file对象......

我可以问一下你想实现什么目标吗?

答案3

这是一个Linux特定的解决方案:/proc/self/fd是当前进程中打开文件句柄的符号链接目录。您只需比较链接值即可。使用子进程时会变得更加复杂,因为子进程将具有不同的 /proc/self 因为它是 pid 相关的符号链接。您可以使用 /proc/$$/fd 解决此问题,其中 $$ 是所需的 pid。

相关内容