使用 Ftrace 跟踪内核函数调用,内核调试必备!

Ftrace 简介

最近使用eBPF做可观测性的项目,接触到了一些内核跟踪工具,其中就包括Ftrace。Ftrace 是 Linux 内核自带的跟踪工具,能够追踪内核中的函数调用、上下文切换、中断处理等。通过 Ftrace,开发人员可以详细了解内核的运行状态,从而更好地优化和调试内核模块。Ftrace 的配置和使用非常灵活,可以通过命令行工具和配置文件来控制其行为。Ftrace 提供了多种跟踪模式,其中主要包括 functionfunction_graph 两种模式。

跟踪模式介绍

1. Function 模式

function 模式是 Ftrace 最基本的跟踪模式,用于记录内核函数的调用。每当一个被跟踪的函数被调用或返回时,Ftrace 都会记录一条日志信息。该模式适用于需要详细了解特定函数调用顺序和频率的场景。

2. Function_graph 模式

function_graph 模式是在 function 模式基础上的增强版,不仅记录函数的调用和返回,还会显示每个函数的调用关系和执行时间。通过 function_graph 模式,可以清晰地看到函数调用的层次结构和各函数的执行时间,适用于需要分析函数调用关系和性能的场景。

使用 Ftrace 进行跟踪

配置 Ftrace

首先,需要确保内核支持 Ftrace,并加载必要的内核模块。可以通过以下命令检查 Ftrace 的状态:

ls /sys/kernel/debug/tracing
cd /sys/kernel/debug/tracing

如果目录存在,则说明 Ftrace 已经启用。接下来,cd进入目录,通过以下步骤配置使用Ftrace:

1. 启用 Function 跟踪

首先,停止追踪并清除当前追踪器:

echo 0 > tracing_on
echo nop > current_tracer

启用 function 跟踪:

echo function > current_tracer

添加需要跟踪的函数(把"do_mkdirat"改成自己要追踪的函数):

echo do_mkdirat > set_ftrace_filter

启用跟踪栈:

echo 1 > options/func_stack_trac

开始跟踪:

echo 1 > tracing_on

查看追踪:

cat trace

停止跟踪:

echo 0 > tracing_on

Function跟踪结果解析

[root@localhost tracing]# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 2/2   #P:1
#
#                                _-----=> irqs-off/BH-disabled
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth
#                              ||| / _-=> migrate-disable
#                              |||| /     delay
#           TASK-PID     CPU#  |||||  TIMESTAMP  FUNCTION
#              | |         |   |||||     |         |
           mkdir-65014   [000] ..... 106404.527038: do_mkdirat <-__x64_sys_mkdir
           mkdir-65014   [000] ..... 106404.527052: <stack trace>
 => 0xffffffffc0bda097
 => do_mkdirat
 => __x64_sys_mkdir
 => do_syscall_64
 => entry_SYSCALL_64_after_hwframe

        可以看到进程 mkdir(PID: 65014)在 CPU 0 上执行了 do_mkdirat 函数,并且这个函数是通过系统调用 __x64_sys_mkdir 进入的。通过堆栈跟踪信息,我们可以看到调用链,从 entry_SYSCALL_64_after_hwframe 开始,到 do_syscall_64,再到 __x64_sys_mkdir,最终调用了 do_mkdirat 函数。

       在 function 模式下,Ftrace 只记录顶层函数调用,而不记录该函数内部调用的其他函数。如果需要查看 do_mkdirat 函数内部调用的函数,可以使用 function_graph 模式,它不仅记录函数的调用,还会记录每个函数内部调用的子函数,并显示每个函数的调用关系和执行时间。

2. 启用 Function_graph 跟踪

首先,停止追踪并清除当前追踪器:

echo 0 > tracing_on
echo nop > current_tracer

 清空过滤:

echo  > set_ftrace_filter

启用 function_graph 跟踪:

echo function_graph > current_tracer

添加需要跟踪的函数:

echo do_mkdirat > set_graph_function

设置追踪调用深度(可选):

echo 4 > max_graph_depth

开始跟踪:

echo 1 > tracing_on

查看追踪:

cat trace

停止跟踪:

echo 0 > tracing_on

Function_graph跟踪结果解析

[root@localhost tracing]# cat trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
 0) ! 618.299 us  |  do_mkdirat();
 ------------------------------------------
 0)  mkdir-65065   =>  mkdir-65069  
 ------------------------------------------

 0)               |  do_mkdirat() {
 0)               |    filename_create() {
 0)               |      __filename_parentat() {
 0)   4.378 us    |        path_parentat();
 0)   5.020 us    |      }
 0)               |      mnt_want_write() {
 0)   0.310 us    |        __mnt_want_write();
 0)   0.922 us    |      }
 0)   0.321 us    |      down_write();
 0)               |      lookup_one_qstr_excl() {
 0)   1.182 us    |        lookup_dcache();
 0)   1.703 us    |        d_alloc();
 0) + 12.033 us   |        ext4_lookup [ext4]();
 0) + 16.351 us   |      }
 0) + 23.995 us   |    }
 0)               |    security_path_mkdir() {
 0)   0.271 us    |      bpf_lsm_path_mkdir();
 0)   0.971 us    |    }
 0)               |    vfs_mkdir() {
 0)   0.290 us    |      from_vfsuid();
 0)   0.270 us    |      from_vfsgid();
 0)               |      from_kuid() {
 0)   0.321 us    |        map_id_up();
 0)   0.841 us    |      }
 0)               |      from_kgid() {
 0)   0.251 us    |        map_id_up();
 0)   0.761 us    |      }
 0)               |      inode_permission() {
 0)   0.251 us    |        make_vfsuid();
 0)   0.301 us    |        make_vfsgid();
 0)   0.381 us    |        generic_permission();
 0)   1.012 us    |        security_inode_permission();
 0)   3.196 us    |      }
 0)   0.271 us    |      mode_strip_sgid();
 0)               |      security_inode_mkdir() {
 0) + 15.079 us   |        selinux_inode_mkdir();
 0)   0.271 us    |        bpf_lsm_inode_mkdir();
 0) + 16.521 us   |      }
 0)               |      ext4_mkdir [ext4]() {
 0)   0.491 us    |        dquot_initialize();
 0) ! 773.775 us  |        __ext4_new_inode [ext4]();
 0) ! 157.675 us  |        ext4_init_new_dir [ext4]();
 0)   4.849 us    |        __ext4_mark_inode_dirty [ext4]();
 0) + 19.497 us   |        ext4_add_entry [ext4]();
 0)   0.552 us    |        ext4_inc_count [ext4]();
 0)   4.839 us    |        __ext4_mark_inode_dirty [ext4]();
 0)   2.344 us    |        d_instantiate_new();
 0)   0.250 us    |        ext4_fc_track_create [ext4]();
 0)   1.393 us    |        __ext4_journal_stop [ext4]();
 0) ! 971.345 us  |      }
 0)   0.491 us    |      fsnotify();
 0) ! 997.414 us  |    }
 0)               |    dput() {
 0)   0.241 us    |      _raw_spin_lock();
 0)               |      d_lru_add() {
 0)   0.821 us    |        list_lru_add();
 0)   1.383 us    |      }
 0)   2.565 us    |    }
 0)   0.231 us    |    up_write();
 0)   0.381 us    |    mnt_drop_write();
 0)   0.250 us    |    dput();
 0)               |    mntput() {
 0)   0.241 us    |      mntput_no_expire();
 0)   0.761 us    |    }
 0)               |    putname() {
 0)   0.361 us    |      kmem_cache_free();
 0)   0.931 us    |    }
 0) # 1032.821 us |  }

可以看到do_mkdirat()函数中的执行调用逻辑就被追踪出来了,便于我们进行性能分析。

总结

Ftrace 是一个非常强大的内核调试工具,能够帮助开发人员详细了解内核函数的调用和性能。通过 functionfunction_graph 两种模式,可以灵活地选择适合的跟踪方式,从而更好地优化和调试内核模块。希望本文对你了解和使用 Ftrace 有所帮助。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LeoCache

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值