Linux内核调试原理和工具介绍--理解静态插装/动态插装、tracepoint、ftrace、kprobe、SystemTap、Perf、eBPF

可以将linux跟踪系统分成Tracer(跟踪数据来自哪里),数据收集分析(如"ftrace")和跟踪前端(更方便的用户态工具)。

1. 数据源(Tracers)

printk 是一种方法, 但是 printk 终归是毫无选择地全量输出, 某些场景下不实用。

Tracepoint属于静态插装, 是散落在内核源代码中的一些 hook,一旦使能,它们便可以在特定的代码被运行到时被触发。比如Ftrace,Perf就使用了Tracepoint采集数据。

Probe技术属于动态插装(Dynamic Instrument) ,是当内核在运行时动态地修改/插入指令。Kprobes就是这种模式的例子。

1.1 Tracepoint示例–Ftrace function tracer

最早 ftrace 是一个 function tracer, 仅能够记录内核的函数调用流程,Ftrace采用 GCC 的 profile 特性在所有内核函数的开始部分加入一段 stub 代码来实现 function trace 功能。

如今 ftrace 已经成为一个 framework, 采用 plugin 的方式支持开发人员添加更多种类的 trace 功能.这些插件也可能是动态插装。

1.2 Tracepoint示例–Perf tracepoint event

Tracepoint event 是内核中的静态 tracepoint 所触发的事件,这些 tracepoint 用来判断程序运行期间内核的行为细节,比如 slab 分配器的分配次数等。

1.3 Probe示例–Kprobe

简介

kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工具,同时它又是其他一些更高级的内核调试工具(比如systemtap)的"基础设施",4.0版本的内核中,强大的eBPF特性也寄生于kprobe之上,所以kprobe在内核中的地位就可见一斑了。

用法

例如!使用kprobes监视我们的计算机上正在打开哪些文件。

$ sudo ./kprobe 'p:myopen do_sys_open filename=+0(%si):string'

您会注意到kprobes接口本身有点粗糙 - 比如,您必须知道文件名参数do_sys_open是在%si寄存器中并取消引用该指针并告诉kprobes系统它是一个字符串。

kprobes在3种情况下很有用:

  1. 您正在跟踪系统调用。系统调用都具有相应的内核函数,例如do_sys_open
  2. 您正在调试网络堆栈中的某些性能问题或者处理文件I / O,并且您了解内核函数,这些函数被调用得足以让您跟踪它们
  3. 你是一个内核开发人员,或者你正试图调试内核bug,有时会发生!

原理

基本上kprobes允许您在运行时动态更改Linux内核的汇编代码(比如,插入额外的汇编指令)以跟踪调用给定指令的时间。

内核源码下有目录下sample/kprobes,该目录下有许多kprobes的例子,可以仿照这些例子写自己的kprobe模块。

以kprobe_example.c为例:

首先 声明一个kprobe结构体,然后定义其中几个关键成员变量,包括symbol_name,pre_handler,post_handler。其中,symbol_name是函数名(kprobe_example.c中该项为do_fork),告诉内核我的探测点放置在了函数do_fork处,pre_handler和post_handler分别表示在执行探测点之前和之后执行的钩子函数。

然后 通过register_kprobe函数注册kprobe即可。

2. 数据收集和分析

2.1 Ftrace

原理

在这里插入图片描述

ftrace使用–debugfs

ftrace 通过 debugfs 向用户态提供访问接口。配置内核时激活 debugfs 后会创建目录 /sys/kernel/debug ,debugfs 文件系统就是挂载到该目录。

mount -t debugfs nodev /sys/kernel/debug

激活内核对 ftrace 的支持后会在 debugfs 下创建一个 tracing 目录 /sys/kernel/debug/tracing 。该目录下包含了 ftrace 的控制和输出文件。

使用示例:

  1. cd /sys/kernel/debug/tracing
  2. echo function > current_tracer
  3. echo do_page_fault > set_ftrace_filter
  4. cat trace

内核配置编译

通常在配置内核时,使用 make menuconfig 会更直观一些。要将 ftrace 编译进内核,可以选中 Kernel hacking下的 Tracers 菜单项。

ftrace 通过 debugfs 向用户态提供了访问接口,所以还需要将 debugfs 编译进内核。激活对 debugfs 的支持,可以直接编辑内核配置文件 .config ,设置 CONFIG_DEBUG_FS=y ;或者在 make menuconfig 时到 Kernel hacking 菜单下选中对 debugfs 文件系统的支持。

配置完成后,编译安装新内核,然后启动到新内核。 注意,激活 ftrace 支持后,编译内核时会使用编译器的 -pg 选项,这是在 kernel/trace/Makefile 文件中定义的。

ftrace跟踪器

ftrace 当前包含多个跟踪器,用于跟踪不同类型的信息,比如进程调度、中断关闭等。可以查看文件 available_tracers 获取内核当前支持的跟踪器列表。在编译内核时,也可以看到内核支持的跟踪器对应的选项。

nop跟踪器 不会跟踪任何内核活动,将 nop 写入 current_tracer 文件可以删除之前所使用的跟踪器,并清空之前收集到的跟踪信息,即刷新 trace 文件。

function跟踪器 可以跟踪内核函数的执行情况;可以通过文件 set_ftrace_filter 显示指定要跟踪的函数。

function_graph跟踪器 可以显示类似 C 源码的函数调用关系图,这样查看起来比较直观一些;可以通过文件 set_grapch_function 显示指定要生成调用流程图的函数。

sched_switch跟踪器 可以对内核中的进程调度活动进行跟踪。

irqsoff跟踪器和 preemptoff跟踪器 分别跟踪关闭中断的代码和禁止进程抢占的代码,并记录关闭的最大时长,preemptirqsoff跟踪器则可以看做它们的组合。

ftrace 还支持其它一些跟踪器,比如 initcall、ksym_tracer、mmiotrace、sysprof 等。ftrace 框架支持扩展添加新的跟踪器。读者可以参考内核源码包中 Documentation/trace 目录下的文档以及 kernel/trace 下的源文件,以了解其它跟踪器的用途和如何添加新的跟踪器。

2.2 SystemTap

SystemTap的框架允许用户开发简单的脚本,用于调查和监视内核空间中发生的各种内核函数,系统调用和其他事件。它是一个允许用户开发自己的特定于内核的取证和监视工具的系统。

原理

在这里插入图片描述
Systemtap基于Kprobe实现。

  • 工作原理是通过将脚本语句翻译成C语句,编译成内核模块。
  • 模块加载之后,将所有探测的事件以钩子的方式挂到内核上,当任何处理器上的某个事件发生时,相应钩子上句柄就会被执行。
  • 最后,当systemtap会话结束之后,钩子从内核上取下,移除模块。

整个过程用一个命令 stap 就可以完成。

安装使用

  1. 编译内核以支持systemtap

我们重新编译内核让其支持systemtap,首先你想让内核中有调试信息,编译内核时需要加上 -g 标志;其次,你还需要在配置内核时将 Kprobe 和 debugfs 开关打开。最终效果是,你能在内核 .config 文件中看到下面四个选项是设置的:

CONFIG_DEBUG_INFO

CONFIG_KPROBES

CONFIG_DEBUG_FS

CONFIG_RELAY

  1. 获取systemtap源码

  2. 编译安装systemtap

2.3 Perf

Perf 是用来进行软件性能分析的工具。

通过它, 应用程序可以利用 PMU, tracepoint 和内核中的特殊计数器来进行性能统计. 它不但可以分析指定应用程序的性能问题 (per thread). 也可以用来分析内核的性能问题, 当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈.

使用示例

perf stat, perf stat -e raw_syscalls:sys_enter ls

perf top

perf record, perf record -e cpu-clock ./t1

3. 前端显示

Trace-cmd

trace-cmd是ftrace的前端,您可以使用它来收集和显示ftrace数据。

火焰图(flame graph)

可以使用Linux perf_events,FreeBSD pmcstat(hwpmc),DTrace,SystemTap和许多其他分析器捕获堆栈样本。

3. eBPF

ebpf tracing

参考

Linux内核调试的方式以及工具集锦

动态追踪技术漫谈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值