我特别感兴趣的是监听 TCP 套接字,但获取套接字的所有套接字(struct sock,如内核的 include/net/sock.h 中所定义)信息就好了。
例如,此 ss 输出显示绑定到 8080 的 TCP 套接字。
tcp LISTEN 20 128 *:8080 *:* uid:500 ino:32355 sk:ffff8801b11ca880
rto:1000 mss:536 cwnd:10
我假设 sk:*** 是此套接字的 (struct sock) 结构的地址。我没有找到任何可以抓取 sk 结构并打印其字段的工具。我可以使用某些东西进入(是内核还是进程?)内存,并将 ffff8801b11ca880 处的数据解释为 (struct sock) 吗?
答案1
该地址位于内核空间中,因为最高 16 位已设置(FFFF)。要继续操作,您需要 GDB 和正在运行的内核的调试符号。我使用的是 CentOS,因此以下方法对我有用:
# yum install gdb
# yum install --enablerepo=base-debuginfo kernel-debuginfo
# gdb /usr/lib/debug/lib/modules/`uname -r`/vmlinux /proc/kcore
之后,你可以像使用用户空间进程一样使用 GDB,只不过它是内核:
(gdb) explore (struct sock *)0xffff8801b11ca880
答案2
这完全取决于您的需要。
结构 sock 中包含的大部分信息(不是struct socket) 仅用于调试。TCP 套接字表的转储包含在/proc/net/tcp,UDP、IGMP、raw、arp、UNIX-domain 也是如此。这是一张普通的 ascii 表,其内容由此输出第 1 行的标题简要概括:
more /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:228B 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15159 1 ffff8801a1ee2300 100 0 0 10 0
1: 00000000:CC4B 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13835 1 ffff8801a1ee0700 100 0 0 10 0
并在人过程(5)页面如下:
/proc/net/tcp
保存 TCP 套接字表的转储。除了调试之外,大部分信息都无用。“sl”值是套接字的内核哈希槽,“local_address”是本地地址和端口号对。“rem_address”是远程地址和端口号对(如果已连接)。“St”是套接字的内部状态。“tx_queue”和“rx_queue”是内核内存使用情况的传出和传入数据队列。“tr”、“tm->when”和“rexmits”字段保存内核套接字状态的内部信息,仅用于调试。“uid”字段保存套接字创建者的有效 UID。
这些信息可以通过以下命令读取和更方便地显示:lsof-i或者网络状态-4。