如果我这样做(在类似 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
答案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。