我正在尝试实现枚举每个进程的所有现有 TCP 连接的代码(类似于netstat -lptn
)。我更喜欢自己实现而不是依赖netstat
。为了做到这一点,我正在解析来自 的数据/proc/<PID>/net/tcp
。
我看到下面列出了许多 TCP 连接,/proc/<PID>/net/tcp
但没有通过命令列出netstat -lptn
。
例如,我看到了这一点/proc/1/net/tcp
,并且/proc/2/net/tcp
有几个 TCP 连接(在 Ubuntu 16 上尝试过)。据我了解,与不应有任何 TCP 连接的进程/proc/1/net/tcp
有关。与之/sbin/init
相关/proc/2/net/tcp
的kthreadd
也不应该有任何 TCP 连接。
答案1
您的方法存在很多误解。我将一一回顾它们。
- 套接字不与特定进程关联。创建套接字时,其引用计数为 1。但是通过不同的方法(例如
dup2
、fork
和文件描述符传递),可能会创建对同一套接字的许多引用,导致其引用计数增加。其中一些引用可以来自打开的文件描述符表,该表本身可以被许多线程使用。这些线程可能属于相同的线程组(PID)或不同的线程组。当您使用该-p
标志时,netstat
它将枚举每个进程可访问的套接字,并尝试为每个已知套接字查找进程。如果有多个候选进程,则不能保证它显示您感兴趣的进程。 /proc/<PID>/net/tcp
不仅列出与该进程相关的套接字。它列出了该进程所属的网络命名空间中的所有 TCPv4 套接字。在默认配置中,系统上的所有进程都属于单个网络命名空间,因此您将看到任何 PID 都相同的结果。这也解释了为什么不使用网络的线程/进程在此文件中包含内容。即使它本身不使用网络,它仍然属于其他进程可以使用网络的网络命名空间。/proc/<PID>/net/tcp
包含侦听和连接的套接字。当你传递-l
给netstat
它时,只会显示正在监听的套接字。为了更接近地匹配输出,您需要-a
而不是-l
./proc/<PID>/net/tcp
仅包含 TCPv4 套接字。您/proc/<PID>/net/tcp6
还需要使用它来查看所有 TCP 套接字。
如果您只对与您自己的进程位于同一命名空间中的套接字感兴趣,则无需迭代不同的 PID。您可以改为使用/proc/net/tcp
andsince/proc/net/tcp6
是/proc/net
的符号链接/proc/self/net
。
答案2
使用/proc/<pid>/fd
- 列出所有打开的文件描述符,包括进程正在使用的套接字。例如
/proc/1278482/fd:
total 0
dr-xr-xr-x. 9 user user 0 Apr 22 23:30 ../
dr-x------. 2 user user 0 Apr 22 23:30 ./
lr-x------. 1 user user 64 Apr 22 23:30 4 -> pipe:[640683476]
lrwx------. 1 user user 64 Apr 22 23:30 3 -> socket:[640754628]
lrwx------. 1 user user 64 Apr 22 23:30 2 -> /dev/pts/10
l-wx------. 1 user user 64 Apr 22 23:30 1 -> /home/user/my_sockets.txt
lrwx------. 1 user user 64 Apr 22 23:30 0 -> /dev/pts/10
然后您可以从中找到相应的条目(例如640754628)/proc/<pid>/net/tcp -> inode[6]
以获取套接字的所有详细信息 - 例如
tcp:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
1864: 0100007F:A650 0100007F:18EB 01 00000000:00000000 00:00000000 00000000 500 0 640754628 1 0000000000000000 20 4 30 10 -1
(上面的示例是到 127.0.0.1:6379 的本地连接)