Linux 4.15内核TCP连接存储位置及端口查询套接字技术问询
Linux 4.15内核TCP套接字存储与相关内核函数答疑
咱们一步一步来拆解你的三个问题,都是TCP栈内核实现里的关键细节:
1. 已建立TCP连接的存储位置
在Linux 4.15中,完成三次握手、处于ESTABLISHED状态的TCP套接字(对应struct sock结构体),是挂载在**tcp_hashinfo结构体**的established哈希链表上的。为了减少多CPU场景下的锁竞争,内核还为每个CPU核心分配了独立的tcp_established_hash(属于per_cpu变量),每个套接字会根据自身的四元组(本地IP+端口、远端IP+端口)计算出哈希值,进而链入对应的哈希桶中。
你可以通过inet_sk(sock)->inet_num(本地端口)、inet_sk(sock)->inet_daddr(本地IP)等字段,从哈希链中匹配到具体的已建立连接。
2. 未完成四次挥手的TCP连接存储位置
这得分不同的关闭状态来区分:
FIN_WAIT1/FIN_WAIT2/CLOSE_WAIT/LAST_ACK状态:这些还在等待对方报文的套接字,依然留在tcp_hashinfo的established哈希链上。只有当它们完成所有关闭步骤,或者超时后,才会被移走或销毁。TIME_WAIT状态:当连接进入TIME_WAIT(主动关闭方收到最终ACK后),对应的套接字会被转移到tcp_hashinfo的timewait_hash哈希表(由tw_bucket结构体组成)中。这个表是专门用来存放等待2MSL时间的连接,避免旧连接的报文干扰新连接,同时也能减轻主哈希链的负担。
3. 仅根据监听端口返回已打开套接字的内核函数
内核里没有直接提供“仅根据监听端口返回所有关联套接字”的现成函数,但你可以基于现有接口实现这个逻辑:
- 找监听套接字本身:可以调用
inet_lookup_listener函数,传入IPPROTO_TCP、本地IP(如果要匹配所有IP可以传INADDR_ANY)和目标端口,就能找到对应的监听套接字。 - 找该端口下的已建立连接:需要遍历
tcp_hashinfo的established哈希链,逐个检查每个sock的inet_sk(sock)->inet_num是否等于目标端口。内核提供了tcp_for_each_sk宏来辅助遍历,但要注意加锁(比如tcp_hashinfo的全局锁或者单个哈希桶的锁),避免并发访问导致的问题。
另外,用户态的ss、netstat工具就是通过读取/proc/net/tcp文件获取这些信息的,而这个文件的内容正是内核遍历上述哈希表后生成的。
内容的提问来源于stack exchange,提问作者Random
相关产品推荐
相关产品推荐

