This got me wondering and I had a look at the Linux kernel source (I'm assuming your question is about Linux).
It appears the answer's more difficult than you'd expect. This TUN/TAP API tutorial page offers some insight. Basically, your program allocates a new TUN/TAP device by opening
/dev/net/tun and sending it the
ioctl. If all goes well, an interface is created, the kernel gives you its name and a file descriptor, and that's how you manage it.
There are two catches here:
- The kernel doesn't store the PID of the process that sent the ioctl in
struct tun_struct (TUN and TAP largely share the same data structures).
- A process may mark an interface as persistent, close its file descriptor and thereafter use it as a normal network interface.
In practice, I suspect 2 doesn't happen much. Checking out an
openvpn process with
lsof reveals it's still got its file descriptor to the TAP device open and obviously using it, but since
/dev/net/tun is a sort of multiplexing device like
/dev/ptmx, you can use
lsof to find out what processes are currently using a TUN/TAP device, but you can't know what process is using what device.
There are oblique ways of solving the underlying problem. For OpenVPN, I use a tunnel setup script that names the
tapX devices with a more descriptive name that includes the basename of the OpenVPN config file. So,
/etc/openvpn/foo.conf leads to a
vpn-foo device. Then I can correlate the OpenvVPN process with the interface it's using. Haven't had to do this with QEmu/KVM yet, though.