跟踪技术(ftrace / eBPF)
见
04-kernel-driver/18-debugging.md和07-advanced/04-perf-profiling.md的扩展。
一、ftrace 完整指南
1. 基础
mount -t tracefs none /sys/kernel/tracing
ls /sys/kernel/tracing
关键文件:
- current_tracer:当前 tracer
- available_tracers:可用 tracer
- tracing_on:1 = 开,0 = 关
- trace:当前 buffer
- trace_pipe:流式
- set_ftrace_filter:函数过滤白名单
- set_ftrace_notrace:黑名单
- set_graph_function:function_graph 目标
2. tracer 类型
| Tracer | 用途 |
|---|---|
nop |
关闭 |
function |
函数调用 |
function_graph |
函数调用图 |
irqsoff |
关中断时间 |
preemptoff |
关抢占时间 |
preemptirqsoff |
两者结合 |
wakeup |
调度延迟 |
wakeup_rt |
实时任务调度延迟 |
mmiotrace |
MMIO 访问 |
blk |
块设备 |
3. function tracer
echo function > current_tracer
echo do_sys_open > set_ftrace_filter
echo 1 > tracing_on
ls
echo 0 > tracing_on
cat trace
4. function_graph
echo function_graph > current_tracer
echo do_sys_open > set_graph_function
echo 1 > tracing_on
ls
echo 0 > tracing_on
cat trace
输出:
3) | do_sys_open() {
3) | /* ... */
3) 0.234 us | do_filp_open();
3) | }
5. trace-cmd 工具
apt install trace-cmd kernelshark
trace-cmd record -p function -l do_sys_open ls
trace-cmd report
trace-cmd record -e all -p function_graph
trace-cmd start -p function -e sched:*
trace-cmd stop
trace-cmd extract
trace-cmd report
6. 自定义事件
ls /sys/kernel/tracing/events/syscalls/
echo 1 > /sys/kernel/tracing/events/syscalls/sys_enter_open/enable
echo 1 > /sys/kernel/tracing/events/syscalls/sys_exit_open/enable
cat trace
7. 内核模块自定义 tracepoint
// mydriver.c
#define CREATE_TRACE_POINTS
#include "trace_mydriver.h"
void my_function(int x)
{
trace_my_event(x);
}
// trace_mydriver.h
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mydriver
#if !defined(_TRACE_MYDRIVER_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_MYDRIVER_H
#include <linux/tracepoint.h>
TRACE_EVENT(my_event,
TP_PROTO(int x),
TP_ARGS(x),
TP_STRUCT__entry(__field(int, x)),
TP_fast_assign(__entry->x = x),
TP_printk("x=%d", __entry->x)
);
#endif
#include <trace/define_trace.h>
查看:
ls /sys/kernel/tracing/events/mydriver/
二、eBPF(进阶)
1. 能力
- 内核级沙箱代码
- 高效、安全、可编程
- 性能接近原生 C
- 可挂载到:kprobe、tracepoint、USDT、socket、xdp
2. bpftrace 单行命令
# 看系统调用次数
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'
# 看 open 文件名
bpftrace -e 'kprobe:do_sys_open { printf("%s\n", argstr(1)); }'
# 看进程启动
bpftrace -e 'tracepoint:sched:sched_process_exec { printf("%s -> %s\n", args->prev_comm, args->filename); }'
# 看网络连接
bpftrace -e 'tracepoint:syscalls:sys_enter_connect { printf("connect by %s\n", comm); }'
3. bpftrace 脚本(.bt)
#!/usr/bin/bpftrace
kprobe:do_sys_open
{
printf("pid %d (%s) open %s\n", pid, comm, argstr(1));
}
kretprobe:do_sys_open /retval < 0/
{
printf("open failed: %d\n", retval);
}
chmod +x script.bt
sudo ./script.bt
4. BCC 工具集
opensnoop-bpfcc # 所有 open()
execsnoop-bpfcc
tcpconnect-bpfcc
biolatency-bpfcc
runqlat-bpfcc
softirqs-bpfcc
hardirqs-bpfcc
profile-bpfcc # CPU 火焰图生成
offcputime-bpfcc # 阻塞时间
5. XDP(eXpress Data Path)
- 网络路径最早点
- 极快(数千万 PPS)
- 用例:DDoS 防护、负载均衡
6. 嵌入式 eBPF
- Linux 5.x+ 嵌入式支持完善
- 限制:需要 JIT、CONFIG_BPF=y
- 工具:bpftrace / bcc 都可移植
三、对比
| 工具 | 优点 | 缺点 |
|---|---|---|
| ftrace | 内置、零依赖 | 仅 Linux 内核 |
| perf | 强大、性能好 | 学习曲线 |
| eBPF | 强大、灵活 | 新工具 |
| LTTng | 跨 tracepoint、用户态 | 复杂 |
| SystemTap | 强大 | 不再主流 |
| dtrace | Solaris 血统 | Linux 移植不完美 |
四、推荐工作流
1. perf top → 发现热点
2. perf record → 采样
3. 火焰图 → 直观展示
4. ftrace → 函数级深度
5. bpftrace → 复杂逻辑
6. 内核 printk → 最终定位
五、嵌入式考虑
- 内核必须支持(CONFIG_FTRACE=y、CONFIG_BPF=y)
- perf 可能有兼容性问题(不同 SoC)
- 内存限制下,trace buffer 不要太大
- 用户态追踪(uprobe)需 CONFIG_UPROBE_EVENTS=y