Perfetto Kernel Function Graph Tracing 实战:用 `function_graph` 追踪内核函数调用树

发布时间:2026/9/17 11:19:47
Perfetto Kernel Function Graph Tracing 实战:用 `function_graph` 追踪内核函数调用树 Perfetto Kernel Function Graph Tracing 实战用function_graph追踪内核函数调用树【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto导读function_graph是 Linux 内核自带的高阶 ftrace tracer能够记录 CPU 上每个内核函数的进入与退出从而还原出内核实际执行的完整调用树及每个函数的耗时。Perfetto 通过linux.ftrace数据源驱动该 tracer把函数调用以嵌套 slice 的形式呈现在时间线上让你无需任何额外插桩就能回答内核此刻到底在做什么。读完本文你将掌握在 Linux 与 Android 上配置enable_function_graph、用function_filters/function_graph_roots精确圈定追踪范围、用 tracebox 录制 trace并在 UI 与 SQL 中分析内核调用树的全套方法。如果你想要的是给内核添加自己的tracepoint 插桩请参考 Instrumenting the kernel with ftrace本文聚焦于零插桩地观测已有内核函数。什么是内核 function_graph 追踪Linux 内核的function_graphtracer 会记录每个内核函数的进入entry与退出exit。Perfetto 通过linux.ftrace数据源驱动该 tracer并将结果可视化为时间线上嵌套的 slice——与用户态 slice 的展示方式完全一致见 system tracing guide。这种方式的巨大价值在于不需要任何你自己的插桩就能回答内核当时实际在做什么。每个内核函数 entry/exit 对会变成一个 slice其持续时间等于该函数内部含被调用者消耗的时间因此调用树读起来就像一个用户态火焰图。需要注意这是一个**高带宽high-bandwidth**功能如果追踪的函数过多事件流会瞬间淹没 trace buffer。因此它被设计为必须与过滤器配合使用——这一点会在下文反复强调。前置要求Requirements要启用 function graph 追踪环境必须同时满足以下条件内核编译选项内核需以CONFIG_FUNCTION_GRAPH_TRACER编译。可用以下命令确认支持cat /sys/kernel/tracing/available_tracers输出中必须包含function_graph。内核符号表ftrace 配置中必须设置symbolize_ksyms: true。否则每个函数只会显示为一段十六进制地址。内核符号必须在录制时解析事后无法用trace_processor bundle补上原因详见 Symbolization: kernel symbols。Android 平台限制function graph 仅在debuggableuserdebug/eng构建上可用且自Android U起才引入。权限要求traced_probes必须以 root 运行或降低kptr_restrict既是为了读取/proc/kallsyms也是为了控制内核 tracer。TraceConfig 配置详解相关配置项全部位于FtraceConfig中其完整定义见 protos/perfetto/config/ftrace/ftrace_config.proto配置项类型说明enable_function_graphbool开启function_graphtracer内核随之产生funcgraph_entry/funcgraph_exit事件function_filtersrepeated string一组 glob仅匹配到的函数被追踪对应内核set_ftrace_filterfunction_graph_rootsrepeated string一组 glob匹配到的函数**及其全部被调用者callees**被追踪对应内核set_graph_functionfunction_graph_max_depthuint32限制根函数之下最多追踪多少层调用对应内核max_graph_depthperfetto v51 起引入Android 25Q3 支持symbolize_ksymsbool必需项用于将函数地址解析为函数名WARNING永远要用function_filters和/或function_graph_roots约束追踪范围。追踪所有内核函数会产生海量事件流会在毫秒级填满 buffer而且几乎毫无用处。配置示例追踪调度器函数及其全部调用者 10 秒原文档给出的完整可运行配置如下funcgraph.cfgbuffers { size_kb: 65536 fill_policy: DISCARD } data_sources { config { name: linux.ftrace ftrace_config { symbolize_ksyms: true enable_function_graph: true # Trace these functions and all of their callees. function_graph_roots: __schedule # Optionally also keep a flat set of functions of interest. function_filters: handle_mm_fault function_graph_max_depth: 10 } } } duration_ms: 10000用tracebox录制./tracebox -c funcgraph.cfg --txt -o funcgraph.pftrace关于如何搭建tracebox及 Linux 上所需的权限参见 system tracing guide。配置项的语义细节结合源码进一步解读上述配置的精确行为function_filters与function_graph_roots的区别前者是扁平函数集合只追踪点名函数本身后者追踪函数及所有 callees形成一棵调用子树。两者可同时设置此时只有同时匹配 filter 的 callees才会被追踪——因此如果两者同时使用通常应把全部 roots 也加入function_filtersproto 注释原文If setting both, you most likely want all roots to also be included infunction_filters。glob 语法function_filters支持通配符例如sched*可指定多条所有匹配的函数都会被追踪语义与内核 ftrace 的set_ftrace_filter文件一致见 ftrace_config.proto。function_graph_max_depth仅对第一个启用 function_graph 的追踪会话生效proto 注释明确说明 Only respected for the first tracing session that enables function_graph tracing因为它直接写内核全局的max_graph_depth。对内置事件的影响当enable_function_graph为 true 时FtraceConfigMuxer会隐式地向事件集合插入两个内置 ftrace 事件ftrace/funcgraph_entry与ftrace/funcgraph_exit见 ftrace_config_muxer.cc。你无需也不应在ftrace_events中手动列出它们。底层实现配置如何落到内核FtraceConfigMuxer::SetupConfigsrc/traced/probes/ftrace/ftrace_config_muxer.cc展示了配置到内核 tracefs 的完整映射清空已有的set_ftrace_filter、set_graph_function与max_graph_depth仅在本次会话是第一个启用 funcgraph 的会话时执行避免打断进行中的 traceAppendFunctionFilters(function_filters)→ 追加到.../set_ftrace_filterAppendFunctionGraphFilters(function_graph_roots)→ 追加到.../set_graph_functionSetMaxGraphDepth(function_graph_max_depth)→ 写入.../max_graph_depthSetCurrentTracer(function_graph)→ 切换当前 tracer 为function_graph并置funcgraph_on true。源码注释ftrace_config_muxer.cc揭示了两个重要设计tracer 不可中途切换trace 进行期间 tracer 不能被改变因此RemoveConfig中没有清理逻辑当前 tracer 会一直保持到所有数据源结束之后由ftrace_controller显式调用ResetCurrentTracer。这正解释了多个并发 ftrace 数据源使用不同 tracer 会导致数据源被拒绝的原因。过滤器是内核有状态累积的Perfetto 不自行维护过滤器集合而是让内核把多个数据源的过滤器有状态地合并AppendFunctionFilters因为所有想要 funcgraph 的并发数据源会共享全部已启用函数解析器不做按数据源的事件分流且不能在 trace 中途移除函数但可能追加。UI 中的展示Function graph 调用以嵌套 slice 呈现线程运行期间发生的调用被挂到该线程下的Funcgraph轨道track空闲 CPUswapper空闲任务上发生的调用被分组到每个 CPU 各自的swapperN -funcgraph轨道。你可以选中任意 slice 查看函数名与耗时并像其他 slice 轨道一样使用火焰图/聚合flamegraph/aggregation功能。这一展示逻辑在 trace_processor 导入层有精确对应ParseFuncgraphEntry/ParseFuncgraphExitsrc/trace_processor/importers/ftrace/ftrace_parser.cc会依据事件的pid选择轨道pid ! 0普通线程 → 通过kThreadFuncgraphBlueprint创建线程级轨道静态名 Funcgraphpid 0空闲线程swapper。注释特别说明idle 线程是隐式的所有 CPU 的 swapper 共享线程 id 0若用线程级轨道会冲突多个 swapper 可能并发运行因此回退为按 CPU 的全局轨道kCpuFuncgraphBlueprint轨道名即swapper%u -funcgraphftrace_parser.cc。此外函数名解析通过InternedKernelSymbolOrFallback(evt.func(), seq_state)完成——这依赖录制期symbolize_ksyms生成的符号表如果符号表缺失这里就只能回落为十六进制地址。SQL 查询Function graph 调用就是普通 slice因此存放在slice表中可用标准 SQL 查询。例如找出累计耗时最多的内核函数SELECT slice.name, COUNT(*) AS calls, SUM(dur) AS total_dur FROM slice JOIN track ON slice.track_id track.id WHERE track.name Funcgraph GROUP BY slice.name ORDER BY total_dur DESC LIMIT 20;要点说明过滤条件是track.name Funcgraph即线程级的 Funcgraph 轨道swapperN -funcgraph轨道名称不同如需统计空闲 CPU 上的调用需按对应名称过滤由于每个 entry/exit 对生成一个 slicedur即函数内部含 callees的真实耗时SUM(dur)可以直接给出按函数聚合的内核 CPU 时间分布任何适用于普通 slice 的分析手段如火焰图聚合、按进程/线程下钻在这里都同样有效。Troubleshooting函数显示为十六进制地址如0xffffffff8108abcd未设置symbolize_ksyms: true或traced_probes无法读取/proc/kallsyms非 root /kptr_restrict过高。这必须在录制时解决事后无法补救参见 Symbolization: kernel symbols。完全没有 function graph 数据确认available_tracers中包含function_graph且配置里至少设置了function_filters/function_graph_roots之一内核函数过滤集合为空时tracer 无事可记。数据源被拒绝data source rejectedfunction graph 无法与另一个使用不同内核 tracer的并发linux.ftrace数据源同时运行——如源码注释所述内核 tracer 在 trace 中途无法切换见 ftrace_config_muxer.cc 中 Unable to enable function_graph tracing since a concurrent ftrace data source is using a different tracer 的日志分支。总结Perfetto 对内核function_graphtracer 的支持把观测内核实际执行路径的成本降到了极低一份包含enable_function_graph、symbolize_ksyms与过滤器的linux.ftrace配置即可录制tracebox 负责采集trace_processor 负责把 entry/exit 事件还原为带函数名与耗时的嵌套 sliceUI 与 SQL 侧则复用完整的 slice 分析能力。掌握过滤器的正确用法function_filters扁平点名 vsfunction_graph_roots递归子树、function_graph_max_depth限制深度是让这一高带宽功能真正可用的关键。延伸阅读系统追踪指南tracebox 搭建与权限内核符号解析原理FtraceConfig 完整字段定义ftrace 数据源配置合并实现funcgraph 事件解析与轨道归属实现【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考