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
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
EEVDF 调度器:Linux 6.6 为什么换掉了 CFS
Linux 6.6 用 EEVDF 取代了 CFS 的 SCHED_NORMAL 选取逻辑。从 1995 年原始论文的 lag、eligibility、virtual deadline,到 commit 147f3ef 只重写 placement/pick/preempt,再到本机内核 6.6 上读 sched/debug 把每个任务的 vruntime、eligible 标志、deadline 一一对上 vd=ve+r/w,外加 nice 带宽与 base_slice 抢占两组实测,讲清换的是哪一块、延迟敏感任务凭什么先跑。
【操作系统百科】Windows 内核与 Linux 的关键差异
NT Executive/Kernel/HAL 分层、Object Manager 与 handle、IRP 驱动栈、IOCP 完成端口 vs epoll/io_uring、EPROCESS/KTHREAD vs task_struct、Registry vs 文件配置,以及 WSL2 为何选择 Hyper-V 轻量 VM。
【操作系统百科】实时 OS 巡礼
硬实时与软实时的可调度性边界、VxWorks/QNX/Zephyr 机制对照、Linux PREEMPT_RT 与主线合入、DO-178C/ISO 26262 认证语境,以及选型决策树。
【操作系统百科】Unikernel
Unikernel 在云上为什么没成主流?MirageOS、IncludeOS、Unikraft、OSv 的设计取舍——库操作系统、启动时间、工具链、调试困难、POSIX 兼容。