第 9 章 显微镜下的内核:跟踪、剖析与黑盒的终结
这一章,我们要解决一个尴尬的问题。
当你面对一个行为诡异的内核时,你通常会怎么做?如果它还会报错,哪怕只是一个 Oops 或者 Kernel Panic,我们都该谢天谢地——因为那是它在求救,至少它告诉了你它死在哪了。最可怕的情况不是崩溃,而是「病态」:系统还能跑,但就是慢得离谱;或者某个功能间歇性失灵,就像幽灵一样时有时无;再或者,你只是单纯地想知道:「到底是谁触发了这个中断?」「这个函数到底被调用了几次?」
在传统的调试手段里,我们像是在打手电筒找东西——printk 是手电筒,kgdb 是放大镜。它们都很好,但都有一个共同的缺陷:你是主动出击的。你必须预设一个断点,或者在代码里插一句打印。如果你的预设错了,你什么都看不到。你就像一个在黑屋子里乱摸的人,摸到了就是运气,摸不到就是常态。
我们需要一种更高级的手段。不是「打手电筒」,而是装「监控摄像头」。我们需要一种能默默记录系统运行轨迹的能力,不需要预设断点,不干扰系统运行,事后还能像回放录像一样分析每一秒发生了什么。
这就是内核跟踪的世界。
在这里,我们会遇到两个容易混淆的近义词:Tracing(跟踪) 和 Profiling(剖析/性能分析)。
理解它们的区别很重要,因为很多人混用这两个词,导致选错了工具。
Tracing(跟踪) 是连续的、细节的。它关注的是「流程」。它就像飞机上的黑匣子,记录下每一次函数调用、每一次参数传递、每一次上下文切换。它的目的是回答「在某一时刻,系统具体做了什么」。它的数据量通常很大,因为它是全量的。
Profiling(剖析) 是统计的、抽样的。它关注的是「热点」。它就像定时拍摄的照片,每 10 毫秒看一眼 CPU 在干嘛。如果 CPU 有 50% 的时间都在执行函数 A,那你就会知道 A 是性能瓶颈。它的目的是回答「时间都去哪儿了」。它的数据量相对较小,因为它只记录频率,不记录每一次细节。
这两种能力,一个抓点(热点),一个抓面(流程),合在一起才是完整的内核可视性。而这一章,我们要讲的主角,就是 Linux 内核里内置的那套最强大的跟踪框架——Ftrace,以及基于它衍生出的各种现代工具生态。
但这并不是一个轻松的话题。Ftrace 本身复杂且底层,直接用它的接口(那些 /sys/kernel/debug 里的伪文件)会让人抓狂。所以我们会像剥洋葱一样:先讲最底层的 Ftrace 机制,让你理解它是如何通过编译器插桩近乎「魔术」地记录每一个函数调用的;再讲 trace-cmd 这种命令行前端,让你不用每次都手 echo 字符串;最后讲 KernelShark 这种 GUI 工具,让你看到真正的「时间线」。
准备好了吗?我们要把显微镜打开,看看这个精密机器内部最真实的运作图景。
9.1 技术准备
在开始折腾之前,我们先确认一下装备。好消息是,这一章的硬件环境没有什么变化——你依然只需要那台标准的 Ubuntu 20.04 LTS 开发机(或者虚拟机)。所有的代码示例依然躺在本书的 GitHub 仓库里:https://github.com/PacktPublishing/Linux-Kernel-Debugging。
但这一章我们会引入两个新朋友:LTTng 和 Trace Compass。
LTTng(Linux Trace Toolkit - next generation)是一套工业级的跟踪系统,比 Ftrace 更重、更强,适合复杂的用户空间+内核空间联合跟踪。而 Trace Compass 则是用来可视化 LTTng 数据的 GUI 工具。
安装步骤:
打开你的终端,这俩工具在 Ubuntu 20.04 的默认源里都有,直接 apt 即可:
sudo apt update
sudo apt install lttng-tools lttng-modules-dkms babeltrace tracecompass
(注:lttng-modules-dkms 会自动编译并安装 LTTng 的内核模块,这一步需要你的系统已经装好了编译内核所需的头文件和构建工具,也就是我们在前面章节里一直标配的那套环境。)
装完之后,我们可以随手验证一下:
$ lttng --version
lttng (LTTng Control) 2.10.7 - lttng-tools (2.10.7)
- Website: https://lttng.org
- Documentation: https://lttng.org/docs
- Git tree: https://git.lttng.org
...
看到版本号弹出来,就说明这一步稳了。
工作区建议:
虽然不是强制的,但我建议你在你的工作目录里新建一个文件夹专门放这一章的实验数据。因为跟踪工具产生的 .dat 文件或者 CTF(Common Trace Format)文件会不少,别把它们和你的源码混在一起,不然以后清理起来很痛苦。
mkdir -p ~/kd_ch9_tracing
cd ~/kd_ch9_tracing
除此之外,没有别的花哨要求了。这一章的重点不在于搭建环境,而在于如何用那些已经存在的工具,去「看」到以前看不见的东西。