Linux内核学习(十):内核追踪必备技能–ftrace

  • Post author:
  • Post category:linux




Linux内核学习(八):内核追踪必备技能–ftrace

在学习内核的过程中,肯定免不了对于内核的调试与运行状态跟踪,这里来学习一下ftrace,真是个神奇的东西。

内容来自《奔跑吧 Linux内核》



1、前言

ftrace最早出现在Linux 2.6.27版本中,其设计目标简单,基于

静态代码插桩技术



不需要用户通过额外的编程来定义跟踪行为。

(打桩这个根据字面意思就知道是打标记点,然后将标记点连接操作,形容出轨迹)

静态代码插桩技术比较可靠,不会因为用户的不当使用而导致内核崩溃。ftrace的名字由function trace而来,它利用gcc编译器的

profile特性在所有函数入口处添加了一段插桩代码

,ftrace重载这段代码来实现跟踪功能。gcc编译器的“-pg”选项会在每个函数入口处加入mcount的调用代码,原本mcount由libc实现,因为内核不会链接libc库,因此ftrace编写了自己的mcount stub函数。

(go里面也有这个名字的库)

在使用ftrace之前,需要确保内核配置编译了其配置选项。

CONFIG_FTRACE=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_IRQSOFF_TRACER=y
CONFIG_SCHED_TRACER=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_PREEMPT_TRACER=y

这里我们可以看出ftrace 相关配置选项比较多,针对不同的跟踪器有各自对应的配置选项。

ftrace 通过debugfs文件系统向用户空间提供访问接口,因此需要在系统启动时挂载debugfs,可以修改系统的/etc/fstab文件或手工挂载。(上一篇学习了Debugfs)

mount -t debugfs debugfs /sys/kernel/debug

在/sys/kernel/debug/trace目录下提供了各种跟踪器和事件,一些常用的选项如下。

  • available_tracers:列出当前系统支持的跟踪器。

  • available_events:列出当前系统支持的事件。

  • current_tracer:设置和显示当前正在使用的跟踪器。使用echo命令可以把跟踪器的名字写入该文件,即可以切换不同的跟踪器。默认为nop,即不做任何跟踪操作。

  • trace:读取跟踪信息。通过cat命令查看ftrace记录下来的跟踪信息。

  • tracing_on:用于开始或暂停跟踪。

  • trace_options:设置ftrace的一些相关选项。

  • ftrace 当前包含多个跟踪器,很方便用户跟踪不同类型的信息,例如进程睡眠唤醒、抢占延迟的信息。查看 available_tracers 可以知道当前系统支持哪些跟踪器,如果系统支持的跟踪器上没有用户想要的信息,就必须在配置内核时自行打开,然后重新编译内核。




常用的ftrace跟踪器如下。

  • nop:不跟踪任何信息。将nop写入current_tracer文件可以清空之前收集到的跟踪信息。

  • function:跟踪内核函数执行情况。

  • function_graph:可以显示类似C语言的函数调用关系图,比较直观。

  • wakeup:跟踪进程唤醒信息。

  • irqsoff:跟踪关闭中断信息,并记录关闭的最大时长。

  • preemptoff:跟踪关闭禁止抢占信息,并记录关闭的最大时长。

  • preemptirqsoff:综合了irqoff和preemptoff两个功能。

  • sched_switch:对内核中的进程调度活动进行跟踪。

下面来展开讲讲其中的几个跟踪器



2、irqs跟踪器

当中断被关闭(俗称关中断)时,CPU 不能响应其他的事件,

如果这时有一个鼠标中断,要在下一次开中断时才能响应这个鼠标中断,这段延迟称为中断延迟。

(拿来跟踪这个中断关闭的时间是多久)

向current_tracer文件写入irqsoff字符串即可打开irqsoff来跟踪中断延迟。整个栗子看看?

# cd /sys/kernel/debug/tracing/
# echo 0 > options/function-trace //关闭function-trace可以减少一些延迟
# echo irqsoff > current_tracer
# echo 1 > tracing_on[...] //停顿一会儿
# echo 0 > tracing_on
# cat trace

来看看结果

在这里插入图片描述

在这里插入图片描述

文件的开头显示当前跟踪器为irqsoff,并且显示其版本信息为v1.1.5,运行的内核版本为4.0。

显示当前最大的中断延迟是259μs,跟踪条目和总共跟踪条目为4条(#4/4),另外VP、KP、SP、HP值暂时没用,#P:4表示当前系统可用的CPU一共有4个。

task: ps-6143表示当前发生中断延迟的进程是PID为6143的进程,名称为ps。

started at和ended at显示发生中断的开始函数和结束函数分别为__lock_task_sighand和_raw_spin_unlock_irqrestore。

ftrace信息表示的内容分别如下。

cmd:进程名字为“ps”。

pid:进程的PID号。

CPU#:该进程运行在哪个CPU上。

irqs-off:“d”表示中断已经关闭。

need_resched:“N”表示进程设置了 TIF_NEED_RESCHED 和PREEMPT_NEED_RESCHED标志位;“n”表示进程仅设置了TIF_NEED_RESCHED标志位;“p”表示进程仅设置了PREEMPT_NEED_RESCHED标志位。

hardirq/softirq:“H”表示在一次软中断中发生了一个硬件中断;“h”表示硬件中断发生;“s”表示软中断;“.”表示没有中断发生。

preempt-depth:表示抢占关闭的嵌套层级。

time:表示时间戳。如果打开了latency-format选项,表示时间从开始跟踪算起,这是一个相对时间,方便开发者观察,否则使用系统绝对时间。

delay:用一些特殊符号来延迟的时间,方便开发者观察。

“$”表示大于 1s,“#”表示大于1000ms,“!”表示大于100ms,“+”表示大于10ms。最后要说明的是,文件最开始显示中断延迟是259ms,但是在里显示306ms,这是因

为在记录最大延迟信息时需要花费一些时间。



3、 preemptoff跟踪器

**当抢占关闭时,虽然可以响应中断,但是高优先级进程在中断处理完成之后不能抢占低优先级进程直至打开抢占,**这样也会导致抢占延迟。和irqsoff跟踪器一样,

preemptoff跟踪器用于跟踪和记录关闭抢占的最大延迟。

(跟踪这里抢占关闭的时间是多久)



4、preemptirqsoff跟踪器

在优化系统延迟时,如果能快速定位何处关中断或者关抢占,这个看名字就是上面两个的综合体。(我觉得这个追踪器的原因就是确定哪里关闭中断或者抢占的时间是多少)



5、function跟踪器

function 跟踪器会记录当前系统运行过程中所有的函数。如果只想跟踪某个进程,可以使用set_ftrace_pid。

(跟踪器跟踪函数的进入和退出,这使跟踪器能够了解被调用函数的深度。函数图跟踪器可以使人眼更容易跟踪内核中的执行流程)



6、动态ftrace

在配置内核时打开了CONFIG_DYNAMIC_FTRACE选项,就可以支持动态ftrace功能。

set_ftrace_filter和set_ftrace_notrace这两个文件可以配对使用。

**其中,前者设置要跟踪的函数,后者指定不要跟踪的函数。**在实际调试过程中,我们通常会被ftrace提供的大量信息淹没,

因此动态过滤的方法非常有用。



7、事件跟踪

ftrace 里的跟踪机制主要有两种,分别是函数和跟踪点(trace point)。

前者属于“傻瓜式”操作,后者可以理解为一个Linux内核中的占位符函数,内核子系统的开发者通常喜欢利用它来调试。

**跟踪点可以输出开发者想要的参数、局部变量等信息。**跟踪点的位置比较固定,一般都是内核开发者添加上去的,可以把它理解为传统C语言程序中#if DEBUG部分。如果在运行时没有开启DEBUG,那么是不占用任何系统开销的。

事件跟踪还支持另一个强大的功能,即可以设定跟踪条件,做到更精细化的设置。每个跟踪点都定义一个格式(format),其中定义了该跟踪点支持的域。



小结

其实大家看到这里,如果你没用过这些,其实内心存在疑惑是很正常的,因为你没有体会到这个用处,但是当你进一步加深学习的时候,你用到的时候,你起码今天看了这个,有一天你遇到后,你会知道这个是什么?应该去查询那个方面的资料?原来它是拿来干这个的啊。

具体例子等后面用到的时候再做记录吧。



版权声明:本文为weixin_45264425原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。