使用trace-cmd跟踪Linux内核函数:一次愉快的内核探险
1. 第一次亲密接触trace-cmd
和ftrace
1.1 ftrace
: 内核的秘密侦探
想象一下,如果你能有一个工具,它像一个隐身的侦探一样,在你不打扰它的日常工作的情况下,悄悄地告诉你内核里都在发生什么。这就是ftrace
!它是Linux内核自带的一个跟踪利器,专门用来窥探内核内部的世界。通过ftrace
,你可以看到函数是如何调用的,了解各种事件的发生,甚至还能找到性能瓶颈。简单来说,ftrace
就像是内核的"心灵捕手",帮你理解它的内心世界。
1.2 trace-cmd
: 让侦探工作变得更简单
现在,假设我们的侦探(ftrace
)虽然很厉害,但是有时候报告有点复杂,不容易看懂。这时候就需要一个好助手了------trace-cmd
登场!这个用户态工具就是为了让ftrace
的使用更加直观、便捷而设计的。它就像给侦探配了一个翻译机,把复杂的内核语言转换成我们容易理解的话。有了trace-cmd
,启动跟踪、查看数据都变得轻而易举。
1.3 trace-cmd
与ftrace
: 组合出击
说到关系,trace-cmd
就好比是ftrace
的私人助理。它简化了配置过程,并且让输出的数据更容易消化,这样开发者就不用直接去捣鼓那些神秘的/sys/kernel/debug
文件了。这种组合就像是拥有了一套高级音响系统,其中ftrace
是主机,而trace-cmd
则是遥控器,让你可以轻松控制一切。
2. trace-cmd
基本语法
2.1 可以跟踪什么: trace-cmd list
想要知道你的侦探工具(trace-cmd
)能帮你找到什么样的线索吗?使用trace-cmd list
命令,你可以列出所有可用的事件源和可以监控的内核函数。这就像在探险之前先查看地图,了解哪些地方值得探索。通过这个命令,你能看到系统中所有的可追踪事件、函数以及它们所属的子系统。
常用参数和示例:
-
-t
:列出当前系统上启用的所有追踪器(tracers)。追踪器不仅仅是简单的记录事件,它们通常会提供特定类型的追踪功能或模式。例如,function_graph
追踪器可以展示函数调用的层级关系。bashtrace-cmd list -t # 输出示例: timerlat osnoise hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop
最常用的就是
function
和function_graph
,下文会演示他们的作用。 -
-s
:列出所有可用的事件分类。每个事件分类代表一个内核子系统的事件集合。这些事件都是内核代码里预定义好的;而function
跟踪器这可以跟踪任意的内核函数。当然这些预定义的事件输出的信息更详细一点。 -
-e [regex]
:列出当前系统上启用的所有事件分类中的详细事件,或者根据正则表达式regex
过滤特定的事件。如果你只对网络相关的事件感兴趣,可以这样做:bashtrace-cmd list -e net: # 输出示例: net:netif_receive_skb_list_exit net:netif_rx_exit net:netif_receive_skb_exit ...
-
-f [regex]
:列出所有可用于过滤的函数。这些是系统中你能够追踪或作为过滤条件的函数。你可以通过正则表达式来筛选特定前缀的函数,比如所有以vfs_
开头的文件系统操作相关函数:bashtrace-cmd list -f ^vfs_ # 输出示例: vfs_fadvise vfs_fallocate vfs_truncate ...
通过上述命令及其参数,你可以详细查看trace-cmd可以监控哪些东西。
2.2 开始跟踪: trace-cmd record
当你已经选定了要跟踪的目标后,就可以启动追踪了!trace-cmd record
就是你用来"部署"侦探到现场的命令。它可以记录内核活动,并将数据保存到一个文件中供后续分析。这里有几个常用的选项可以帮助你更精确地控制追踪过程:
-
-p tracer
:指定一个追踪器。常见的追踪器包括function
(用于追踪函数调用)、function_graph
(用于绘制函数调用图),以及其他如preemptirqsoff
、irqsoff
等。要查看可用的追踪器列表,请参见trace-cmd list -t
。 -
-e event
:指定要追踪的事件。各种静态跟踪点已经被添加到Linux内核中,它们按照子系统分组,你可以启用整个子系统的事件或指定具体的事件。事件格式为"subsystem:event-name"
。例如,"-e sched_switch"
会启用sched_switch
事件,而"-e sched"
则会启用sched
子系统下的所有事件。 -
-l function-name
:限制function
和function_graph
追踪器仅追踪给定的函数名。支持完整的正则表达式解析或基本的通配符匹配。如果过滤器仅包含字母数字、下划线、星号、问号和句点,则会被视为基本通配符;若要强制解析为正则表达式,可以在过滤器前加上^或在后面加上$。 -
-g function-name
:对于function_graph
插件,该选项会创建给定函数的调用图,即只追踪该函数及其直接或间接调用的所有其他函数。
举个例子,如果你想追踪所有的内核函数调用,可以这样执行:
bash
sudo trace-cmd record -p function
而如果你只想追踪某个特定函数,比如sys_open
,则可以这样做:
bash
sudo trace-cmd record -p function -l sys_open
2.3 查看跟踪报告: trace-cmd report
完成了追踪之后,最重要的一步就是解读收集到的数据。这就是trace-cmd report
发挥作用的地方------它能够读取由record
命令生成的追踪文件,并以易于理解的方式展示出来。你可以从这些报告中了解到每个事件的发生时间、持续多久、涉及哪些进程等重要信息。
为了查看最近一次的追踪结果,只需简单地运行:
bash
sudo trace-cmd report
此外,report
命令还支持多种格式化选项,允许你根据需要调整输出内容,比如按时间排序、显示CPU编号等。这使得数据分析更加直观和高效。通过结合trace-cmd list
、trace-cmd record
和trace-cmd report
这三个基本命令,你可以深入探究Linux内核的行为,无论是日常调试还是性能优化都能得心应手。
3. trace-cmd
使用示例
为了让您更好地理解如何使用trace-cmd
,我们举一些常用的例子。通过这些示例,您可以学习到如何设置追踪、捕捉特定的内核活动以及如何分析生成的数据。
3.1 跟踪事件源
- 使用
trace-cmd list -s
查看所有可以监控的事件源
3.1.1 监控网络事件: -e net
要监控与网络相关的事件,你可以使用-e
选项指定你感兴趣的事件类型。例如,如果你想查看所有与网络子系统相关的事件,可以这样做:
bash
sudo trace-cmd record -e net -F ping www.baidu.com -c1
这条命令会启动对所有网络相关事件的追踪,并且只记录由ping
命令(发送一个ICMP请求)触发的活动。执行完上述命令后,运行ping
命令,完成后按Ctrl+C
停止追踪。然后使用trace-cmd report
来查看和分析结果。
3.1.2 跟踪调度器行为
如果你想探究Linux调度器的行为,可以使用sched_switch
事件来追踪进程之间的切换:
bash
# 开始追踪sched_switch事件
sudo trace-cmd record -e sched:sched_switch sleep 3
这个命令开始追踪调度器事件,并等待3秒后自动结束追踪。这段时间内发生的任何进程间的切换都会被记录下来。之后,你可以使用trace-cmd report
来检查哪个进程在何时被调度了。
3.1.3 跟踪所有系统调用
如果你想要全面监控系统的每一个系统调用,包括它们的参数和返回值,可以使用sys_enter
和sys_exit
事件。这对于深入了解应用程序与操作系统之间的交互非常有用,尤其是在调试或性能分析时。通过这种方式,你可以捕捉到每个系统调用的进入(sys_enter
)和退出(sys_exit
)时刻,并查看其传递给内核的参数以及从内核返回的结果。
例如,假设你想追踪执行ls
命令期间的所有系统调用活动,可以使用以下命令:
bash
sudo trace-cmd record -e syscalls:sys_enter_* -e syscalls:sys_exit_* -F ls
这条命令的具体含义如下:
-e syscalls:sys_enter_*
:启用所有系统调用进入事件的追踪。-e syscalls:sys_exit_*
:启用所有系统调用退出事件的追踪。-F ls
:指定只记录由ls
命令触发的系统调用活动。
3.2 跟踪具体函数
有时候你需要知道某个特定的系统调用是如何被执行的,比如打开文件(sys_open
)。可以通过过滤函数名来进行追踪:
bash
# 开始追踪sys_open及其相关函数调用
sudo trace-cmd record -p function -l *open* -F cat /etc/passwd
这段命令将启动一个函数追踪器,专门针对名字中包含open
的所有函数,同时仅记录由cat
命令触发的活动。这可以帮助你了解当读取文件时,内核内部发生了哪些函数调用。完成操作后,使用trace-cmd report
来查看详细的函数调用列表。
3.3 跟踪函数调用图
假设你想要深入了解文件系统中的vfs_open
函数是如何工作的,包括它调用了哪些其他函数。你可以使用function_graph
追踪器来创建一个调用图,这将帮助你看到vfs_open
及其所有子函数的执行流程。为了确保只跟踪由特定命令(如cat
)引发的函数调用,可以结合-g
和-F
选项:
bash
# 开始追踪vfs_open函数调用图
sudo trace-cmd record -p function_graph -g vfs_open -F cat /etc/passwd
这条命令的意思是:启动function_graph
追踪器,专门追踪vfs_open
函数及其调用链,并且只记录由cat
命令触发的活动。之后你可以使用trace-cmd report
查看详细的调用图。从报告中可以看到每个函数的调用时间、持续时间和调用层次结构,这对调试和性能分析非常有用。
4. 总结
trace-cmd
结合内核自带的ftrace
工具,为Linux内核提供了强大的跟踪功能。ftrace
作为内置的跟踪机制,能悄无声息地揭示内核内部运作细节,如函数调用流程和事件发生情况。而trace-cmd
则是一个用户空间工具,旨在简化ftrace
的使用,使启动跟踪、查看数据变得简单直观。
通过trace-cmd list
命令,用户可以列出所有可用的事件源、追踪器、事件以及可过滤的函数,这有助于规划追踪策略。trace-cmd record
用于启动追踪并记录内核活动到文件中,支持指定追踪器、事件或特定函数等选项,以便更精确地控制追踪过程。最后,trace-cmd report
读取追踪文件并展示结果,帮助分析每个事件的时间、持续时长及涉及的进程等信息,从而深入了解内核行为,无论是日常调试还是性能优化都能得心应手。