使用ftrace 来跟踪系统问题 - ftrace 介绍
虽然之前一直听说过 ftrace,但从来没将它用在实战中,在一次客户排查问题中,遇到了比较奇怪的现象,一位精通内核的朋友建议使用 ftrace 来定位一下。虽然那一次并没有使用 ftrace,但也让我觉得,后面我们势必要提供 ftrace 相关的工具帮助我们在线上定位问题,所以自己也决定重新学习使用下 ftrace,当然也决定写一系列的相关出来,这里就先简单介绍下 ftrace。
首先我们需要知道,什么是 ftrace?根据 Linux Doc 的介绍,ftrace 是一个 Linux 内部的 trace 工具,能够帮助开发者和系统设计者知道内核当前正在干啥,从而更好的去分析性能问题。
Ftrace 能帮我们分析内核特定的事件,譬如调度,中断等,也能帮我们去追踪动态的内核函数,以及这些函数的调用栈还有栈的使用这些。它也能帮我们去追踪延迟,譬如中断被屏蔽,抢占被禁止的时间,以及唤醒一个进程之后多久开始执行的时间。
可以看到,使用 ftrace 真的能做到对系统内核非常系统的剖析,甚至都能通过 ftrace 来学习 Linux 内核,不过在更进一步之前,我们需要学会的是 - 如何使用 ftrace。
要使用 ftrace,首先就是需要将系统的 debugfs 或者 tracefs 给挂载到某个地方,幸运的是,几乎所有的 Linux 发行版,都开启了 debugfs/tracefs 的支持,所以我们也没必要去重新编译内核了。
在比较老的内核版本,譬如 CentOS 7 的上面,debugfs 通常被挂载到 /sys/kernel/debug 上面(debug 目录下面有一个 tracing 目录),而比较新的内核,则是将 tracefs 挂载到 /sys/kernel/tracing ,无论是什么,我都喜欢将 tracing 目录直接 link 到 /tracing 。后面都会假设直接进入了 /tracing 目录,后面,我会使用 Ubuntu 16.04 来举例子,内核版本是 4.13 来举例子。
我们使用 ls 来看看目录下面到底有什么:
可以看到,里面有非常多的文件和目录,具体的含义,大家可以去详细的看官方文档的解释,后面只会重点介绍一些文件。
我们可以通过 available_tracers 这个文件知道当前 ftrace 支持哪些插件。
通常用的最多的就是 function 和 function_graph ,当然,如果我们不想 trace 了,可以使用 nop 。我们首先打开 function :
上面我们将 function 写入到了 current_tracer 来开启 function 的 trace,我通常会在 cat 下 current_tracer 这个文件,主要是防止自己写错了。
然后 ftrace 就开始工作了,会将相关的 trace 信息放到 trace 文件里面,我们直接读取这个文件就能获取相关的信息。
我们可以设置只跟踪特定的 function
当然,如果我们不想 trace schedule 这个函数,也可以这样做:
或者也可以这样做:
Function filter 的设置也支持 *match , match* , *match* 这样的正则表达式,譬如我们可以 echo '*lock*'
相比于 function , function_graph 能让我们更加详细的去知道内核函数的上下文,我们打开 function_graph :
我们也可以只跟踪某一个函数的堆栈
上面提到了 function 的 trace,在 ftrace 里面,另外用的多的就是 event 的 trace,我们可以在 events 目录下面看支持那些事件:
上面列出来的都是分组的,我们可以继续深入下去,譬如下面是查看 sched 相关的事件:
对于某一个具体的事件,我们也可以查看:
不知道大家注意到了没有,上述目录里面,都有一个 enable 的文件,我们只需要往里面写入 1,就可以开始 trace 这个事件。譬如下面就开始 trace sched_wakeup 这个事件:
我们也可以 trace sched 里面的所有事件:
当然也可以 trace 所有的事件:
从上面的例子可以看到,其实使用 ftrace 并不是那么方便,我们需要手动的去控制多个文件,但幸运的是,我们有 trace-cmd ,作为 ftrace 的前端, trace-cmd 能够非常方便的让我们进行 ftrace 的操作,譬如我们可以使用 record 命令来 trace sched 事件:
然后使用 report 命令来查看 trace 的数据:
当然,在 report 的时候也可以加入自己的 filter 来过滤数据,譬如下面,我们就过滤出 sched_wakeup 事件并且是 success 为 1 的。
大家可以注意下 success == 1 ,这其实是一个对事件里面 field 进行的表达式运算了,对于不同的事件,我们可以通过查看起 format 来知道它的实际 fields 是怎样的,譬如:
上面只是简单的列出了 ftrace 相关的使用,后续我会在写一些我们或者业界是如何用 ftrace 来解决问题的。另外,我们正在用 ftrace 开发非常多的性能诊断工具,如果你对这一块感兴趣,欢迎联系我 tl@pingcap.com 。