本文目录导读:

- 方法一:使用 BPF 跟踪特定内核函数(最推荐)
- 方法二:使用 ftrace(较古老、不需要安装额外工具)
- 方法三:通过 /proc 观察是否触发了 TCP NODELAY 变化(间接观察)
- 方法四:定制内核 tracepoint(高级)
- 总结建议
tcp_autocork_trace 并不是一个标准的 Linux 内核 tracepoint 或内核函数名,你可能是想追踪 TCP 自动 cork(自动合并小包) 的行为,或者是把 tcp_autocork 和 trace 搞混了。
在 Linux 内核中,与“自动 cork”相关的函数是 tcp_autocork()(位于 net/ipv4/tcp_output.c)。这个函数本身没有独立的 tracepoint,但你可以通过以下几种方法来跟踪它的行为:
使用 BPF 跟踪特定内核函数(最推荐)
最精确的方法是使用 bpftrace 或 trace 命令挂载在 tcp_autocork 函数上,适用于内核版本 >= 4.x。
使用 bpftrace 跟踪 tcp_autocork 被调用的次数和进程:
bpftrace -e 'kprobe:tcp_autocork { printf("PID %d (%s) called tcp_autocork\n", pid, comm); }'
查看函数调用时的参数(sk 指针):
bpftrace -e 'kprobe:tcp_autocork { printf("tcp_autocork called by %s, sk=%llx\n", comm, arg0); }'
跟踪 tcp_push 中何时决定使用 cork(更精细的追踪):
因为 tcp_autocork 通常在 tcp_push 中被调用,你可以同时跟踪这两个函数:
bpftrace -e '
kprobe:tcp_push { @start[tid] = nsecs; }
kretprobe:tcp_push /@start[tid]/ {
$delta = (nsecs - @start[tid]) / 1000;
if ($delta > 1000) { printf("tcp_push took %d us by %s\n", $delta, comm); }
delete(@start[tid]);
}
kprobe:tcp_autocork {
printf("tcp_autocork triggered by %s\n", comm);
}'
注意: 你需要安装
bpftrace,并且通常需要 root 权限。
使用 ftrace(较古老、不需要安装额外工具)
使用 trace-cmd 或直接操作 /sys/kernel/tracing(现代内核路径 /sys/kernel/debug/tracing 已废弃)。
使用 trace-cmd 记录 tcp_autocork 的调用:
trace-cmd record -p function -l tcp_autocork # 运行你的网络程序(curl/wget) # 完成后按 Ctrl+C trace-cmd report
直接使用 ftrace(不推荐新手,但可用):
cd /sys/kernel/tracing echo function > current_tracer echo tcp_autocork > set_ftrace_filter echo 1 > tracing_on # 运行你的测试 cat trace_pipe echo 0 > tracing_on
注意: 如果内核没有导出
tcp_autocork符号,set_ftrace_filter可能报错,你可以先用available_filter_functions确认是否支持。
通过 /proc 观察是否触发了 TCP NODELAY 变化(间接观察)
自动 cork 的核心作用是:当检测到 socket 采用了 NODELAY,但在收到了部分数据后主动推迟发送(有点像 cork)。
你可以通过监听 /proc/net/tcp 或使用 ss 命令观察 TCP 状态变化,但这只能看到最终结果,很难定位何时触发了 cork 决策。
# 观察某个连接的发送缓冲区状态变化 ss -tempi dst <目标IP> | grep -E "cork|nodelay"
但这通常不会直接显示 tcp_autocork 被调用。
定制内核 tracepoint(高级)
如果你有修改内核代码的权限,可以在 tcp_autocork() 中的关键决策点(if (tp->nonagle & TCP_NAGLE_CORK))加入 trace_printk() 或创建新的 tracepoint。
例如在 net/ipv4/tcp_output.c 的 tcp_autocork 函数中:
if (sk->sk_pacing_rate > sk->sk_sndbuf / 3) {
// 加入自定义 trace
trace_printk("tcp_autocork: triggering cork for sk=%p\n", sk);
...
}
然后使用 trace-cmd 等方式可以直接抓取自定义的打印信息。
总结建议
| 方法 | 难度 | 是否需要 root | 效果 | 推荐场景 |
|---|---|---|---|---|
| bpftrace kprobe | 中 | 是 | 直接触发,能看进程和参数 | 开发调试首选 |
| ftrace (trace-cmd) | 低 | 是 | 只能看函数入口,无参数 | 确认是否被调用 |
| ss / /proc | 低 | 否 | 间接观察,不精确 | 快速排查 |
| 定制内核 | 高 | 是 | 精确,可定制 | 内核开发者 |
最推荐你从 bpftrace 开始,因为它最灵活且无需编译内核,希望这个回答能解决你的问题!
标签: 内核网络栈调试