Linux 网络: sequence file
文章目录
使用 ss
、netstat
等命令查看 TCP 连接信息时,它们可能会从文件 /proc/net/tcp
读取 tcp socket 信息。
|
|
而使用 file
命令查看 /proc/net/tcp
文件时,提示是 empty:
|
|
使用 mount
命令查看一下,发现 /proc
是一个 proc
类型的文件系统:
|
|
所以,/proc/net/tcp
并不是一个真正的文件,而是一个虚拟文件,它的内容是内核中的数据结构的映射。
实际上,/proc/net/tcp
是一个 sequence file,它的内容是一系列的 records,每个 record 代表一个 TCP socket。
本文不打算详细介绍 procfs 下 sequence file 的具体实现,而是抓住 sequence file 的核心 seq_file
接口,介绍一下 sequence file 的基本原理。
seq_file
接口
sequence file 参考资料:The seq_file Interface。
seq_file
接口定义如下:
|
|
该接口比较简单,它定义了 4 个回调函数:
start
: 开始一次会话,并返回一个 iterator。stop
: 结束本次会话。next
: iterator 前进到下一个位置,并返回一个 iterator。show
: 根据 iterator,将一条 record 数据写入到seq_file
。
实现了这个接口后,当用户态空间打开一个 sequence file 时,read()
系统调用会调用该接口的回调函数,从而一行一行地将数据写入到用户态空间。
获取 TCP socket 信息
所以,当需要从 /proc/net/tcp
读取 tcp socket 信息时,推荐 line by line 地读取该文件,而不是一次性读取整个文件。
当有大量 tcp socket 时,非常不推荐一次性读取整个文件,也不推荐使用 man 7 inet_diag
的方式获取全部的 tcp socket 信息;即使 inet_diag
方式对代码更加友好。
小结
本质上,sequence file 是内核向用户态空间传递数据的一种方式,类似 netlink,但它的功能简单且单一。
因其简单,内核里不少地方都通过 sequence file 向用户态空间传递数据;全局搜索 struct seq_operations
,发现有 400 多个地方使用了 sequence file。
其实,bpf 子系统也基于 sequence file 机制,实现了动态 record 的 sequence files;即 bpf_iter
。
文章作者 Leon Hwang
上次更新 2024-04-03