Notes
main
main
  • Introduction
  • linuxKernel
    • tips
    • make_help
    • old linux
      • compile_linux0.11
      • TestEnvironment
      • load_setup
      • get_hard_data
    • list
    • plist
    • fifo
    • idr
    • xarray
    • rbtree
    • maple_tree
    • syscall
    • bitmap
    • page
    • page_flags
    • page_size
    • page mapcount
    • page refcount
    • folio
    • slub
      • proc_slabinfo
      • slub_theory
      • kmalloc_kfree
      • kmem_cache
      • slab_alloc
      • slab_free
      • proc_meminfo_SReclaimable_SReclaimable
    • vmalloc
    • brk
    • mmap
    • mremap
    • mprotect
    • madvise
    • read
    • write
    • shmem
    • huge_page
    • page_fault
    • rmap
    • lru
    • multi-gen-LRU
    • page_reclaim
    • page_cache
    • page_table
    • rcu
    • kvm
    • aarch64_boot
    • tracing_system
    • cache_coherence_and_memory_consistency
    • cpu_speculates
    • mmap_lock
    • per-vma_lock
    • cgroup
    • symbol
    • campact
    • page_ext
    • mempool
    • kernelstack
    • filesystem
    • io_stack
    • workingset
    • ioremap
    • sched_period
  • linuxDebug
    • openocd_openjtag
    • i2c_tools
    • objdump
    • addr2line
    • gdb_useage
    • debug_linux_kernel_via_gdb
    • debug_linux_module_via_gdb
    • early_boot
    • sequentially_execute
    • dynamic_debug
    • research_linuxKernel_by_patch
    • tracefs
    • ebpf
    • bpftrace
    • perf
    • flame_graph
    • crash
    • ASAN_HWASAN_MTE_check_mem_bug
    • page_owner
    • vmtouch
    • fio
    • benchmark
  • linuxSystem
    • common
      • system_version
      • procfs
      • proc_sys_vm
      • cmd_ps
      • makefile
      • file_descriptor
      • psi
      • ulimit
      • top
      • delay_accounting
    • ubuntu
      • custom_kernel
      • get_cmd_src
      • record_ssh_info
      • log
      • run_custom_script
      • repo
      • cockpit
      • nfs
      • tftp
      • misc
    • fedora
      • system_upgrade
      • custom_kernel
      • lvextend
      • yt-dlp
      • jellyfin
  • linuxDriver
    • i2c_peripherals_driver
    • spi_peripherals_driver
    • gpio_subsystem
    • IRQ_driver
    • blockIO_unblockIO_async
    • linux_own_driver
    • misc_device
    • input_device
    • timer
    • atomic_spinlock_semaphore_mutex
    • lcd
    • touch_screen
    • debugfs
    • v4l2
    • mmap
  • hardware
    • paging_mmu_pt
    • iommu
  • process_thread_scheduler
    • scheduler01
    • scheduler02
    • scheduler03
    • scheduler04
    • scheduler05
    • scheduler06
  • memory_management
    • mm1
    • mm2
    • mm3
    • mm4
    • mm5
  • input_output_filesystem
    • io_fs_01
    • io_fs_02
    • io_fs_03
    • io_fs_04
  • lock_and_lockup_detector
    • general_lock
    • hung_task
    • softLockup_hardLockup
    • crash_experiment
  • MIT_6.S081
    • 6.S081_Operating_System_Engineering
    • Schedule.md
    • Class
      • Overview
      • Administrivia
    • Labs
      • Tools
      • Guidance
      • startup
      • syscall
      • page_table
      • Calling_Convention
      • traps
    • xv6
      • xv6
    • References.md
  • qemu
    • qemu_buildroot
    • qemu_busybox.md
    • Serial.md
    • demo_mini2440
      • 0_compilation_error_summary
      • 1_compilation_steps
      • 2_operation_mode
      • 3_transplant_tools_libraries
      • 4_tools_use
      • reference_website
  • tools
    • getKernelSourceCodeList
    • nat
    • shell
    • translating
    • YouCompleteMe
    • cscope
    • global
    • vscode
    • vim
    • binary
    • markdown
    • draw
    • git
    • tig
    • tmux
    • mail_client
    • download_patchset_from_LKML
    • minicom
    • clash
  • other
    • interview
    • interview_c_base
    • know_dontknow
    • Stop-Ask-Questions-The-Stupid-Ways
    • How-To-Ask-Questions-The-Smart-Way
    • docker
    • buildroot
    • rv32_to_rv64
Powered by GitBook
On this page
  • 简介
  • 使能 tracefs 功能
  • tracefs 挂载位置
  • 节点解析
  • 技巧
  • 输出格式
  • 例子
  • 阅读 function_graph 输出的日志

Was this helpful?

  1. linuxDebug

tracefs

Previousresearch_linuxKernel_by_patchNextebpf

Last updated 5 months ago

Was this helpful?

简介

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

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 功能

CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_FUNCTION_GRAPH_RETVAL=y
CONFIG_KPROBE_EVENTS=y

tracefs 挂载位置

$ mount -t debugfs none /sys/kernel/debug
$ ls /sys/kernel/debug/tracing
or
$ ls /sys/kernel/tracing

节点解析

节点
描述

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 跟踪一个函数往上的调用路径

输出格式

# tracer: nop
#
# entries-in-buffer/entries-written: 358096/10552611   #P:6
#
#                                _-----=> irqs-off/BH-disabled
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth
#                              ||| / _-=> migrate-disable
#                              |||| /     delay
#           TASK-PID     CPU#  |||||  TIMESTAMP  FUNCTION
#              | |         |   |||||     |         |
         systemd-1       [002] d..1.   127.240361: contention_begin: 00000000610328f2 (flags=SPIN|WRITE)
         systemd-1       [002] d..1.   127.240987: contention_end: 00000000610328f2 (ret=0)

第1行 tracer 类型

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

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

例子

function tracer

$ echo function > current_tracer       # 指定tracer类型
$ echo func_name > set_ftrace_filter   # 指定要过滤的函数
$ echo 1 > tracing_on
$ cat trace

function_graph tracer

$ echo function_graph > current_tracer  # 指定tracer类型
$ echo func_name > set_graph_function   # 指定要跟踪的函数,显示 func_name() 调用哪些函数
$ echo 1 > tracing_on
$ cat trace

tracepoint event

$ echo 1 > events/xxx/enable           # 使能指定的 event
$ echo stacktrace > events/xxx/trigger # 打印函数调用栈
$ echo 1 > tracing_on
$ cat trace

kprobe event

$ echo 'p vm_mmap_pgoff+296 comm=$comm sem=%x0 count=+0(%x0) owner=+8(%x0)' > kprobe_events  # 添加 vm_mmap_pgoff() 偏移 296 位置的动态 event(打印进程名、信号量等)
$ echo 'comm=="ABC"' > events/kprobes/p_vm_mmap_pgoff_296/filter                             # 进行过滤,只显示进程名为 ABC 的信息
$ echo 1 > options/stacktrace                                                                # 打印函数调用栈
$ echo 1 > events/kprobes/p_vm_mmap_pgoff_296/enable                                         # 使能指定的 event
$ echo 1 > tracing_on
$ cat trace

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

/* offset      |    size */  struct zone {
/*    168      |       8 */    const char *name;

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

过滤技巧,跟踪多个函数

## 情景1:函数名类似,使用正则表达式匹配
$ echo 'dev_attr_*' > set_ftrace_filter
$ cat set_ftrace_filter
dev_attr_store
dev_attr_show

## 情景2:追加某个函数
$ echo __kmalloc >> set_ftrace_filter
$ cat set_ftrace_filter
__kmalloc
dev_attr_store
dev_attr_show

## 情景3:基于模块过滤
$ echo 'write*:mod:ext4' >> set_ftrace_filter
$ cat set_ftrace_filter
__kmalloc
dev_attr_store
dev_attr_show
write*:mod:ext4

## 情景4:从过滤列表中删除某个函数,使用 ! 前缀
$ echo '!__kmalloc' >> set_ftrace_filter
$ cat set_ftrace_filter
dev_attr_store
dev_attr_show
write*:mod:ext4

前端工具 trace-cmd

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

## 查看 func_name() 是否可用
$ trace-cmd list -f func_name

## 过滤 func_name(),trace 数据保存到 trace.dat 文件
$ trace-cmd record -p function -l func_name
$ trace-cmd report

## 过滤 func_name(),trace数据不保存到 trace.dat 文件
$ trace-cmd start -p function -l func_name
$ trace-cmd show

## 显示 func_name() 调用栈
$ trace-cmd start -p function -l func_name --func-stack
$ trace-cmd show

## 显示 func_name() 调用哪些函数
$ trace-cmd start -p function_graph -g func_name
$ trace-cmd show

## 只显示 a.out 执行时,func_name() 调用哪些函数
$ trace-cmd start -p function_graph -g func_name ./a.out
$ trace-cmd show

## 只显示 a.out 执行时,func_name() 调用哪些函数,并且显示每一个函数的返回值
$ trace-cmd start -p function_graph -g func_name -O funcgraph-retval ./a.out
$ trace-cmd show

参数解释:

  • -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 输出的日志,如下:

$ vim -u Documentation/trace/function-graph-fold.vim <trace_log>
tracing_system