可观测性 ftrace


介绍

ftrace是Function Tracer的意思,最开始主要用于记录内核函数运行轨迹;随着功能的逐渐增加,演变成一个跟踪框架。

ftrace的运行不需要额外的程序,它内置在内核中,通过debugfs文件系统和用户交互。当然也有一些用户态程序方便用户交互,比如trace-cmd、kernelshark。

工作原理

ftrace机制的执行,依赖于gcc的-pg编译选项,-pg选项在每个函数执行前插入mcount(和体系架构有关,不同架构名字有所差异)。在未启用追踪功能的时候,插入的指令为NOP,不做任何事情,启用追踪功能之后,NOP指令会被替换成ftrace_caller。

mcout是一个trampoline跳床,它返回函数的返回值,提供了一种在原流程中执行桩函数的机制。

ftrace_caller 工作如下图所示

使用

ftrace的使用比较简单,与ftrace交互的API位于debufs文件系统中,通常在/sys/kernel/debug/目录下。

因为ftrace是直接内置于内核中的的,所以使用它需要配置内核支持。

通常开启如下几项配置

CONFIG_FUNCTION_TRACER
CONFIG_FUNCTION_GRAPH_TRACER
CONFIG_DYNAMIC_FTRACE

其分为静态和动态trace,常使用动态trace。

查看支持哪些tracer

# cat /sys/kernel/debug/tracing/available_tracers
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop

设置使用那个tracer

# echo wakeup > /sys/kernel/debug/tracing/current_tracer

查看当前使用的tracer

# cat /sys/kernel/debug/tracing/current_tracer
wakeup

启用/停用追踪

echo 1 > /sys/kernel/debug/tracing/tracing_on
echo 0 > /sys/kernel/debug/tracing/tracing_on

查看追踪的结果 (从文件中)

# cat /sys/kernel/debug/tracing/trace |more
# tracer: wakeup
#
# wakeup latency trace v1.1.5 on 5.4.0-42-generic
# --------------------------------------------------------------------
# latency: 8450 us, #16610/16610, CPU#3 | (M:desktop VP:0, KP:0, SP:0 HP:0 #P:4)
#    -----------------
#    | task: systemd-journal-575 (uid:0 nice:-1 policy:0 rt_prio:0)
#    -----------------
#
#                  _------=> CPU#
#                 / _-----=> irqs-off
#                | / _----=> need-resched
#                || / _---=> hardirq/softirq
#                ||| / _--=> preempt-depth
#                |||| /     delay
#  cmd     pid   ||||| time  |   caller
#     \   /      |||||  \    |   /
 systemd-1       3d...    0us+:      1:120:R   + [003]   575:119:R systemd-journal
 systemd-1       3d...   14us : <stack trace>
 => __trace_stack
 => probe_wakeup
 => ttwu_do_wakeup
 => ttwu_do_activate
 => try_to_wake_up
 => default_wake_function
 => autoremove_wake_function
 => __wake_up_common
 => __wake_up_common_lock
 => __wake_up
 => ep_poll_callback
....

查看追踪结果,直接输出到命令行,与上面输出结果一样。

# cat /sys/kernel/debug/tracing/trace_pipe

查看支持的动态追踪点

# cat /sys/kernel/debug/tracing/available_filter_functions |more
trace_initcall_finish_cb
initcall_blacklisted
do_one_initcall
do_one_initcall
trace_initcall_start_cb
run_init_process
try_to_run_init_process
match_dev_by_label
match_dev_by_uuid
rootfs_init_fs_context

查看当前设置的动态追踪点,默认所有的都支持。

# cat /sys/kernel/debug/tracing/set_ftrace_filter
#### all functions enabled ####

监控某些函数

# echo xxx某函数 > /sys/kernel/debug/tracing/set_ftrace_filter

设置tracer 查看监控

# cat /sys/kernel/debug/tracing/trace

实验

ping 127.0.0.1 查看trace

  1. 设置动态追踪函数 icmp_rcv 、__sys_socket
# echo icmp_rcv > /sys/kernel/debug/tracing/set_ftrace_filter
# cat set_ftrace_filter
icmp_rcv
  1. 设置tracer
# echo function_graph > /sys/kernel/debug/tracing/current_tracer
# cat current_tracer
function_graph
  1. ping 127.0.0.1
# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.113 ms
^C
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2031ms
rtt min/avg/max/mdev = 0.035/0.088/0.116/0.037 ms
  1. 查看追踪情况
# cat trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
   2)   9.289 us    |  icmp_rcv();
   2)   1.422 us    |  icmp_rcv();
   2) + 26.285 us   |  icmp_rcv();
   2)   6.820 us    |  icmp_rcv();
   2) + 25.768 us   |  icmp_rcv();
   2)   6.255 us    |  icmp_rcv();

参考

https://en.wikipedia.org/wiki/Ftrace https://www.cnblogs.com/arnoldlu/p/7211249.html https://docs.kernel.org/trace/ftrace.html

https://lwn.net/Articles/322666

欢迎大家转发分享。未经授权,严禁任何复制、转载、摘编或以其它方式进行使用,转载须注明来自eBPFLAB并附上本文链接。如果有侵犯到您权益的地方,请及时联系我删除。