我有时会遇到带有分接头接口的机器(例如,当 KVM 运行时)。我如何知道哪个进程附加到 TAP 接口?
答案1
每个文件描述符都有一个/proc/PID/fdinfo/编号条目,例如:
# cat /proc/24332/fdinfo/28
pos: 0
flags: 0104002
mnt_id: 18
iff: tap0123acdc-66
因此,通过接口名称,您可以通过以下方式获取 pid:
# egrep -l iff:.*tap0123acdc-66 /proc/*/fdinfo/* 2>/dev/null|cut -d/ -f3
24332
答案2
这让我感到好奇,我查看了 Linux 内核源代码(我假设你的问题是关于 Linux 的)。
看来答案比你想象的要困难。这TUN/TAP API 教程页面提供了一些见解。基本上,您的程序通过打开/dev/net/tun
并向其发送TUNSETIFF
ioctl
.如果一切顺利,将创建一个接口,内核为您提供其名称和文件描述符,这就是您管理它的方式。
这里有两个问题:
- 内核不存储发送 ioctl 的进程的 PID
struct tun_struct
(TUN 和 TAP 在很大程度上共享相同的数据结构)。 - 进程可以将接口标记为持久,关闭其文件描述符,然后将其用作普通网络接口。
实际上,我怀疑 2 不会发生太多。检查一个openvpn
进程,lsof
发现它仍然打开了 TAP 设备的文件描述符,并且显然正在使用它,但由于/dev/net/tun
是一种像 一样的多路复用设备/dev/ptmx
,您可以使用lsof
来找出当前正在使用 TUN/TAP 设备的进程,但是你无法知道什么进程正在使用什么设备。
有一些间接的方法可以解决根本问题。对于 OpenVPN,我使用隧道设置脚本,使用更具描述性的名称来命名tunX
/设备,其中包括 OpenVPN 配置文件的基本名称。tapX
因此,/etc/openvpn/foo.conf
引出了一个vpn-foo
设备。然后我可以将 OpenvVPN 进程与其使用的接口关联起来。不过,还没有必要使用 QEmu/KVM 来做到这一点。
答案3
在 FreeBSD 或任何其他 BSD 衍生产品上:
ifconfig tap0
应该显示哪个进程连接到该接口:
tap0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=80000<LINKSTATE>
ether 58:9c:fc:10:8f:2b
groups: tap
media: Ethernet autoselect
status: active
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
Opened by PID 2672