tracefs

简介

tracefs 是 Linux 内核自带的调试工具,从久远的 2.6 内核就支持了,可以辅助定位 内核问题,原理参考 tracing_system

tracefs 有以下 tracer:

  1. ftrace tracer(e.g. function tracer, function_graph tracer)

  2. event tracer(e.g. 静态 tracepoint event, 动态 kprobe event)

ftrace tracer

基于 ftrace tracer,通过 current_tracer 节点来激活使用。

event tracer

默认 event 是静态的,并且使用 tracepoint 实现,而利用 kprobe 机制,可以 动态的插入 event,实现静态 event 同样功能。 换句话说,静态 event 只能在代码中使用 tracepoint 写好后进行编译,动态 event 能够在系统运行中利用 kprobe 增加/删除。

最初 kprobe 是以内核模块形式开发(e.g. samples/kprobes/kprobe_example.c), 但是开发代码不方便并且容易影响内核运行的稳定性。如何避免?

  1. 将 kprobe 封装成动态 kprobe event

  2. 通过 eBPF (e.g. bpftrace) 使用 kprobe

基于 event tracer,不需要通过 current_tracer 节点来激活使用。

  1. 静态 event 只需要通过 events/xxx/enable 打开 event 即可

  2. 动态 event,只需要通过 kprobe_events 增加/删除 event,并且通过 events/kprobes/xxx/enable 打开 event 即可。

使能 tracefs 功能

tracefs 挂载位置

节点解析

节点
描述

trace

输出 ftrace buffter 内容

trace_pipe

以 PIPE 方式输出 ftrace buffter 内容

tracing_on

ftrace 总开关

current_tracer

指定 tracer 类型,默认是nop

available_tracers

所有可用的 tracer 类型

set_graph_function

指定要跟踪的函数,能够输出调用哪些函数

set_ftrace_filter

指定要过滤的函数,只输出单一函数

set_event

指定要跟踪的 event

available_events

所有可用的 events

kprobe_events

添加/删除动态 event

trace_marker

用户空间直接写内容到 ftrace buffer 中

set_ftrace_pid

指定要跟踪的进程 pid

trace_options

所有可选功能的打开/关闭情况

options/trace_printk

控制 trace_printk() 是否能够输出 comment 到 ftrace buffer

options/markers

控制 trace_marker 节点是否可写

options/funcgraph-retval

显示 function_graph tracer 的函数返回值

options/funcgraph-retaddr

显示 function_graph tracer 的函数返回地址

options/funcgraph-proc

显示 function_graph tracer 在哪个进程触发

options/func_stack_trace

显示 function tracer 的函数调用栈

options/stacktrace

显示 event 的函数调用栈

events/xxx/format

显示 event 输出格式

events/xxx/filter

过滤 event,如:echo "pid==123" > filter 只显示 pid 123 的 event

events/xxx/trigger

触发 event 的额外操作,如:echo stacktrace > trigger 打印函数调用栈

events/xxx/enable

使能 event

技巧

  • 设置 function_graph tracer + set_graph_function 跟踪一个函数往下的调用路径

  • 设置 function_graph tracer + set_graph_function + funcgraph-retval 跟踪 一个函数返回错误码的调用路径,再加上 kprobe_events 打印函数参数

  • 设置 function_graph tracer + set_graph_function + funcgraph-retaddr 跟踪 一个函数返回地址,利用 faddr2line 获得 inline 函数的调用路径

  • 设置 function tracer + set_ftrace_filter + func_stack_trace 跟踪 一个函数往上的调用路径

  • 设置 event + stacktrace 跟踪一个函数往上的调用路径

输出格式

第1行 tracer 类型

第2行 缓冲区中的事件数以及总数,如:358096/10552611,代表缓冲区因填满而丢失的 事件数为 10552611−358096=10194515)。最后是 CPU数量

其它是记录的事件内容:进程名,PID,运行在哪个CPU上,延迟时间戳(格式:<秒>.<微秒>), 函数名,打印内容

例子

function tracer

function_graph tracer

tracepoint event

kprobe event

注意:如果结构体的成员变量是 char * 类型,如下:

使用 name=+0(+168($argN)) 来打印。

过滤技巧,跟踪多个函数

前端工具 trace-cmd

与前面直接读写/sys/kernel/tracing/xxx一样,如下:

参数解释:

  • -p:指定当前的 tracer,类似 echo function > current_tracer,支持 available_tracers 中的任意一个

  • -l:指定过滤的函数,可以设置多个,类似 echo function_name > set_ftrace_filter

  • -g:指定跟踪的函数,显示调用哪些函数,类似 echo function_name > set_graph_function

  • --func-stack:记录被跟踪函数的调用栈,类似 echo 1 > options/func_stack_trace

  • -O:指定可选功能,如 funcgraph-retval,类似 echo 1 > options/funcgraph-retval

阅读 function_graph 输出的日志

在 Linux Kernel 中有一个 vim 配置文件,用于方便阅读 function_graph 输出的日志,如下:

Last updated

Was this helpful?