Kernel Exploring
  • 前言
  • 支持
  • 老司机带你探索内核编译系统
    • 编译出你的第一个内核
    • 内核编译中的小目标
    • 可能是kbuild中最直接的小目标 – help
    • 使用了一个kbuild函数的目标 – cscope
    • 内核中单个.o文件的编译过程
    • 根目录vmlinux的编译过程
    • 启动镜像bzImage的前世今生
    • setup.bin的诞生记
    • 真假vmlinux–由vmlinux.bin揭开的秘密
    • bzImage的全貌
    • kbuild系统浅析
  • 启动时的小秘密
    • INIT_CALLS的秘密
    • 内核参数
  • 内核加载全流程
    • bootloader如何加载bzImage
    • 内核压缩与解压
    • 内核加载的几个阶段
    • 保护模式内核代码赏析
  • 内存管理
    • 内核页表成长记
      • 未解压时的内核页表
      • 内核早期的页表
      • cleanup_highmap之后的页表
      • 映射完整物理地址
      • 启用init_level4_pgt
    • 自底而上话内存
      • e820从硬件获取内存分布
      • 原始内存分配器--memblock
      • 页分配器
        • 寻找页结构体的位置
        • 眼花的页结构体
        • Node-Zone-Page
        • 传说的伙伴系统
        • Compound Page
        • GFP的功效
        • 页分配器的用户们
      • slub分配器
        • slub的理念
        • 图解slub
      • 内存管理的不同粒度
      • 挑战和进化
        • 扩展性的设计和实现
        • 减少竞争 per_cpu_pageset
        • 海量内存
        • 延迟初始化
        • 内存热插拔
        • 连续内存分配器
    • 虚拟内存空间
      • 页表和缺页中断
      • 虚拟地址空间的管家--vma
      • 匿名反向映射的前世今生
      • 图解匿名反向映射
      • THP和mapcount之间的恩恩怨怨
      • 透明大页的玄机
      • NUMA策略
      • numa balance
      • 老版vma
    • 内存的回收再利用
      • 水线
      • Big Picture
      • 手动触发回收
      • Page Fram Reclaim Algorithm
      • swapfile原理使用和演进
    • 内存隔离
      • memcg初始化
      • 限制memcg大小
      • 对memcg记账
    • 通用
      • 常用全局变量
      • 常用转换
    • 测试
      • 功能测试
      • 性能测试
  • 中断和异常
    • 从IDT开始
    • 中断?异常?有什么区别
    • 系统调用的实现
    • 异常向量表的设置
    • 中断向量和中断函数
    • APIC
    • 时钟中断
    • 软中断
    • 中断、软中断、抢占和多处理器
  • 设备模型
    • 总线
    • 驱动
    • 设备
    • 绑定
  • nvdimm初探
    • 使用手册
    • 上帝视角
    • nvdimm_bus
    • nvdimm
    • nd_region
    • nd_namespace_X
    • nd_dax
      • dev_dax
  • KVM
    • 内存虚拟化
      • Qemu内存模型
      • KVM内存管理
  • cgroup
    • 使用cgroup控制进程cpu和内存
    • cgroup文件系统
    • cgroup层次结构
    • cgroup和进程的关联
    • cgroup数据统计
  • 同步机制
    • 内存屏障
    • RCU
  • Trace/Profie/Debug
    • ftrace的使用
    • 探秘ftrace
    • 内核热补丁的黑科技
    • eBPF初探
    • TraceEvent
    • Drgn
  • 内核中的数据结构
    • 双链表
    • 优先级队列
    • 哈希表
    • xarray
    • B树
    • Maple Tree
    • Interval Tree
  • Tools
  • Good To Read
    • 内核自带文档
    • 内存相关
    • 下载社区邮件
Powered by GitBook
On this page
  • Tracing测试文件目录
  • 使用function tracer
  • 使用function_graph tracer
  • 使用trace_printk()
  • 使用function command
  • 现实谁调用了某个函数
  • Profiling
  1. Trace/Profie/Debug

ftrace的使用

PreviousTrace/Profie/DebugNext探秘ftrace

Last updated 1 year ago

这章我们先来看看如何使用ftrace。

说来惭愧,多少年前同事告诉我这种高级方法的时候,我还觉得麻烦,依然在使用printk。现在回想起来真实井底之蛙啊。

有几个非常不错的参考资料:

  • 内核源码中的

接下来就从来看几个例子:

Tracing测试文件目录

要和trace打交道都是要通过它的debugfs接口,默认情况下这个文件目录在 /sys/kernel/debug/tracing.

你也可以手动挂载到想要的位置:

mount -t tracefs nodev /sys/kernel/tracing

在这个目录下有很多重要的文件,具体每个文件的作用可以在中找到。这里解说几个比较重要的

设置当前使用的tracer

  • current_tracer

  • available_tracer

是否过滤函数

  • available_filter_functions

  • set_ftrace_filter

  • set_graph_function

得到trace输出

  • trace

  • per_cpu/cpu0/trace

  • trace_pipe

控制是否将跟踪输出写入

  • tracing_on

像我这样的初级小白,了解这么几个文件就够用了。

使用function tracer

先来看一个完整的使用方法。

echo 0 > tracing_on
echo function > current_tracer
echo 1 > tracing_on
# wait a while
echo 0 > tracing_on
cat trace
cat per_cpu/cpu0/trace

tracing_on用来控制是否实际输出到trace文件,所以我们在开始和结束时,我们都关掉输出,以免有太多的输出内容。 第二个命令用来指定这次使用的是function trace。因为没有设置函数过滤,所以应该是所有的内核函数都会被记录。 打开输出,停一会儿再关掉后,就可以通过trace文件查看这段时间内的内核运行情况了。

另外还可以通过查看per_cpu/cpu0/trace文件来只观察在cpu0上发生的内核函数调用。这是一个非常不错去除多个cpu之间干扰的好方法。

使用function_graph tracer

这个例子和之前的区别在于选择了不同的tracer,function_graph的话可以打印出函数调用的关系,更加方便理解。

echo 0 > tracing_on
echo function_graph > current_tracer
echo 1 > tracing_on
# wait a while
echo 0 > tracing_on
cat trace
cat per_cpu/cpu0/trace

也就不做过多的解释。

使用trace_printk()

这个函数的用法和printk()一样,只是输出不在console,而是在ftrace的ring buffer。

而且在nop tracer的情况下也能在trace中看到输出。这样就不会被函数调用信息干扰到了。

汗颜,现在才知道这个。

使用function command

方法如下

# echo '__bad_area_nosemaphore:traceoff' > set_ftrace_filter
# cat set_ftrace_filter
#### all functions enabled ####
__bad_area_nosemaphore:traceoff:unlimited

这样就可以在函数__bad_area_nosemaphore触发时,停止trace,留住最后的案发现场。

现实谁调用了某个函数

在学习内核的过程中,我们有时候会想了解一下一个函数都会被谁调用,整个调用栈是什么样子的。ftrace也提供了这个功能。

   [tracing]# echo kfree > set_ftrace_filter
   [tracing]# cat set_ftrace_filter
   kfree
   [tracing]# echo function > current_tracer
   [tracing]# echo 1 > options/func_stack_trace
   [tracing]# cat trace | tail -8
    => sys32_execve
    => ia32_ptregs_common
                cat-6829  [000] 1867248.965100: kfree <-free_bprm
                cat-6829  [000] 1867248.965100: <stack trace>

    => free_bprm
    => compat_do_execve
    => sys32_execve
    => ia32_ptregs_common
   [tracing]# echo 0 > options/func_stack_trace
   [tracing]# echo > set_ftrace_filter

Profiling

Ftrace也能做profile。

   [tracing]# echo nop > current_tracer
   [tracing]# echo 1 > function_profile_enabled
   [tracing]# cat trace_stat/function0 |head
     Function                               Hit    Time            Avg
     --------                               ---    ----            ---
     schedule                             22943    1994458706 us     86931.03 us
     poll_schedule_timeout                 8683    1429165515 us     164593.5 us
     schedule_hrtimeout_range              8638    1429155793 us     165449.8 us
     sys_poll                             12366    875206110 us     70775.19 us
     do_sys_poll                          12367    875136511 us     70763.84 us
     compat_sys_select                     3395    527531945 us     155384.9 us
     compat_core_sys_select                3395    527503300 us     155376.5 us
     do_select                             3395    527477553 us     155368.9 us

没实验成功,以后再看看。

这个用法来自作者的第三篇文章。因为trace的内容太多,这个方法能够在某个函数被调用时停止trace,方便调试时观察到trace信息。

使用手册
LWN 1
LWN 2
Secrets of the Ftrace function tracer
LWN Artical List
Ftrace Kernel Hooks: More than just tracing
使用手册
Secrets of the Ftrace function tracer