ftrace 是内核内置的追踪框架——不需要额外模块,不需要重新编译,生产环境可用。
一、先看图
flowchart TD
APP[用户态<br/>trace-cmd / echo] -->|控制| TRACEFS[tracefs<br/>/sys/kernel/debug/tracing]
TRACEFS --> FTRACE[ftrace 框架]
FTRACE --> FT[function tracer<br/>mcount/fentry]
FTRACE --> FG[function_graph<br/>调用图]
FTRACE --> TP[tracepoints<br/>静态探针]
FTRACE --> HIST[histogram<br/>触发器]
FT --> RING[ring buffer<br/>per-CPU]
FG --> RING
TP --> RING
classDef ctrl fill:#388bfd22,stroke:#388bfd,color:#adbac7;
classDef trace fill:#3fb95022,stroke:#3fb950,color:#adbac7;
class APP,TRACEFS ctrl
class FTRACE,FT,FG,TP,HIST,RING trace
二、基本原理
2.1 mcount / fentry
GCC 编译内核函数时插入 mcount 调用(或
-fpatchable-function-entry 插入 nop)。
function_entry:
nop nop nop nop nop # 5 字节 nop(x86)
...
启用 ftrace 时 → 动态 patch nop 为 call → 跳转到追踪代码。
2.2 零 overhead
未启用时 → nop → 无开销。
三、function tracer
echo function > /sys/kernel/debug/tracing/current_tracer
echo do_sys_openat2 > /sys/kernel/debug/tracing/set_ftrace_filter
echo 1 > /sys/kernel/debug/tracing/tracing_on
cat /sys/kernel/debug/tracing/trace输出每次函数调用的 CPU、时间戳、进程。
四、function_graph
echo function_graph > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/trace 0) | do_sys_openat2() {
0) 0.892 us | getname();
0) | do_filp_open() {
0) 1.234 us | path_openat();
0) 2.567 us | }
0) 4.123 us | }
展示调用栈和耗时 → 性能分析利器。
五、Tracepoints
静态探针,编译时定义:
// include/trace/events/sched.h
TRACE_EVENT(sched_switch, ...)echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
cat /sys/kernel/debug/tracing/tracetracepoints 比函数追踪更稳定 → 不依赖函数名。
六、trace-cmd
trace-cmd record -p function_graph -g do_sys_openat2
trace-cmd report | head -30
# 实时查看
trace-cmd start -p function_graph -g vfs_read
trace-cmd show
trace-cmd stop七、Histogram 触发器
echo 'hist:key=common_pid:val=hitcount:sort=hitcount.descending' > \
/sys/kernel/debug/tracing/events/sched/sched_switch/trigger
cat /sys/kernel/debug/tracing/events/sched/sched_switch/hist内核空间聚合 → 不需要把每条 trace 拷贝到用户态。
八、Synthetic Events
组合多个事件:
echo 'wakeup_lat s32 lat' > /sys/kernel/debug/tracing/synthetic_events
echo 'hist:keys=pid:ts0=common_timestamp.usecs' > \
/sys/kernel/debug/tracing/events/sched/sched_waking/trigger
echo 'hist:keys=next_pid:lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_lat($lat)' > \
/sys/kernel/debug/tracing/events/sched/sched_switch/trigger九、观察
# 可用 tracer
cat /sys/kernel/debug/tracing/available_tracers
# 可用 tracepoints
cat /sys/kernel/debug/tracing/available_events | wc -l
# 可追踪函数
cat /sys/kernel/debug/tracing/available_filter_functions | wc -l
# 当前状态
cat /sys/kernel/debug/tracing/tracing_on十、小结
- ftrace = 内核内置追踪框架 → 动态 patching,未启用零开销
- function/function_graph 追踪函数调用
- tracepoints 是稳定的静态探针
- histogram + synthetic events = 内核空间聚合
- trace-cmd 是友好的前端
参考文献
kernel/trace/Documentation/trace/ftrace.rst- Steven Rostedt, “ftrace: Function Tracer.” 2008
man trace-cmd
工具
trace-cmd- tracefs 文件系统
perf ftrace
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
【操作系统百科】交换
swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。
【操作系统百科】Slab/SLUB 分配器
buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。
【操作系统百科】用户态分配器
glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。