18

我试图弄清楚是什么进程持有 unix 域套接字的另一端。在一些strace输出中,我已经确定了一个给定的文件描述符,该文件描述符涉及我当前正在调试的问题,我想知道哪个进程在另一端。由于该套接字有多个连接,因此仅按路径名是行不通的。

lsof为我提供以下信息:

dbus-daem  4175  mvg   10u  unix 0xffff8803e256d9c0      0t0  12828 @/tmp/dbus-LyGToFzlcG

所以我知道一些地址(“内核地址”?),我知道一些套接字号,我知道路径。我可以在其他地方找到相同的信息:

$ netstat -n | grep 12828
unix  3      [ ]         STREAM     CONNECTED     12828    @/tmp/dbus-LyGToFzlcG
$ grep -E '12828|ffff8803e256d9c0' /proc/net/unix
ffff8803e256d9c0: 00000003 00000000 00000000 0001 03 12828 @/tmp/dbus-LyGToFzlcG
$ ls -l /proc/*/fd/* 2>/dev/null | grep 12828
lrwx------ 1 mvg users 64 10. Aug 09:08 /proc/4175/fd/10 -> socket:[12828]

但是,这些都没有告诉我套接字连接的另一端是什么。我怎么知道哪个进程在控制另一端?

4

2 回答 2

15

在Server FaultUnix & Linux上也提出了类似的问题。公认的答案是,Linux 上的用户空间无法可靠地使用此信息。

一个常见的建议是查看相邻的套接字编号,但ls -l /proc/*/fd/* 2>/dev/null | grep 1282[79]这里没有给出任何结果。netstat也许可以使用输出中的相邻行。似乎存在一种带有和不带有关联套接字名称的连接模式。但我想要某种确定性,而不仅仅是猜测。

一个答案建议一种工具,它似乎能够通过挖掘内核结构来解决这个问题。使用该选项需要内核的调试信息,由该CONFIG_DEBUG_INFO选项生成并由某些发行版作为单独的包提供。基于该答案,使用提供的地址lsof,以下解决方案对我有用:

# gdb /usr/src/linux/vmlinux /proc/kcore
(gdb) p ((struct unix_sock*)0xffff8803e256d9c0)->peer

这将打印连接另一端的地址。查询lsof -U该数字将提供进程 ID 和文件描述符编号等详细信息。

如果调试信息不​​可用,则可以通过了解对等成员在 unix_sock 结构中的偏移量来访问所需的信息。就我而言,在 Linux 3.5.0 for x86_64 上,可以使用以下代码计算相同的地址,而无需依赖调试符号:

(gdb) p ((void**)0xffff8803e256d9c0)[0x52]

我不会对该解决方案的便携性做出任何保证。

于 2012-08-10T10:55:50.150 回答
1

更新:现在可以使用实际接口来执行此操作已有一段时间了。从 Linux 3.3 开始,UNIX_DIAG 功能为此信息提供了一个基于 netlink 的 API,并且 lsof 4.89 及更高版本支持它。有关详细信息,请参阅https://unix.stackexchange.com/a/190606/1820

于 2016-10-27T00:30:32.647 回答