调试与性能分析指南
1. 调试会话示例
1.1 配置串口
要使用 GDB 进行内核调试,首先需要告知 kgdb 使用哪个串口。有两种配置方式:
-
内核命令行
:在命令行中添加
kgdboc=<tty>,<baud rate>
,例如
kgdboc=ttyO0,115200
。
-
运行时通过 sysfs
:设备启动后,将终端名称写入
/sys/module/kgdboc/parameters/kgdboc
文件,如
# echo ttyO0 > /sys/module/kgdboc/parameters/kgdboc
,但这种方式无法设置波特率。
1.2 启动 GDB
在主机上启动 GDB,并选择与运行内核匹配的 vmlinux 文件:
$ arm - poky - linux - gnueabi - gdb ~/linux/vmlinux
GDB 会从 vmlinux 加载符号表并等待进一步输入。
1.3 连接至 kgdb
关闭连接到控制台的终端模拟器,然后在 GDB 中尝试连接到 kgdb,但此时可能会收到无效响应。因为 kgdb 此时未监听连接,需要中断内核。可以通过 SSH 在目标板上启动另一个 shell,并向
/proc/sysrq - trigger
写入
g
来强制内核进入陷阱:
# echo g > /proc/sysrq - trigger
此时目标停止,可再次在 GDB 中连接:
(gdb) set serial baud 115200
(gdb) target remote /dev/ttyUSB0
1.4 调试操作
连接成功后,GDB 接管调试。可以设置断点、检查变量、查看回溯等。例如,设置
sys_sync
断点:
(gdb) break sys_sync
(gdb) c
在目标上输入
sync
会触发断点。
1.5 禁用 kgdboc
调试结束后,若要禁用 kgdboc,将 kgdboc 终端设置为 null:
# echo "" > /sys/module/kgdboc/parameters/kgdboc
1.6 调试早期代码
如果要调试系统启动早期执行的代码,可在命令行中添加
kgdbwait
:
kgdboc=ttyO0,115200 kgdbwait
启动时,控制台会显示等待远程 gdb 连接的信息,此时可关闭控制台并以常规方式从 GDB 连接。
1.7 调试模块
调试内核模块时,由于代码在运行时会重新定位,需要通过 sysfs 获取模块各部分的重定位地址。以模块
mbx
为例:
# cat /sys/module/mbx/sections/.text
# cat /sys/module/mbx/sections/.data
# cat /sys/module/mbx/sections/.bss
在 GDB 中加载模块符号表:
(gdb) add - symbol - file /home/chris/mbx - driver/mbx.ko 0xbf000000 \
- s.data 0xbf0003e8 - s.bss 0xbf0005c0
之后可正常设置断点和检查变量。
1.8 使用 kdb 调试内核代码
kdb 虽没有 kgdb 和 GDB 的全部功能,但它是自托管的,无外部依赖。要通过串口控制台调用 kdb,需先按前文启用 kgdb,再启用
CONFIG_KGDB_KDB
选项。
当强制内核进入陷阱时,会看到 kdb shell:
# echo g > /proc/sysrq - trigger
kdb shell 支持多种命令,如下表所示:
| 命令类型 | 命令 | 说明 |
| ---- | ---- | ---- |
| 获取信息 | ps | 显示活动进程 |
| | ps A | 显示所有进程 |
| | lsmod | 列出模块 |
| | dmesg | 显示内核日志缓冲区 |
| 断点操作 | bp | 设置断点 |
| | bl | 列出断点 |
| | bc | 清除断点 |
| | bt | 打印回溯 |
| | go | 继续执行 |
| 检查内存和寄存器 | md | 显示内存 |
| | rd | 显示寄存器 |
例如设置
sys_sync
断点:
kdb> bp sys_sync
kdb> go
输入
sync
会触发断点。
1.9 分析内核 Oops 信息
当内核进行无效内存访问或执行非法指令时,会在内核日志中写入 Oops 消息。以一个 Oops 消息为例,通过分析
PC is at mbx_write+0x24/0xbc [mbx]
可知最后执行的指令在
mbx_write
函数中,偏移为 0x24 字节。
通过 GDB 的
disassemble /s
命令可找到对应的代码行:
$ arm - poky - linux - gnueabi - gdb mbx.ko
(gdb) disassemble /s mbx_write
分析可知
m
变量可能为 null 指针,导致 Oops。修改驱动代码初始化指针后可解决问题。
1.10 保存 Oops 信息
若系统在控制台启用前崩溃或挂起后崩溃,可能看不到 Oops 信息。可在内存内容未损坏时,重启进入引导加载程序查看内存。先在
System.map
中查找
__log_buf
的位置:
$ grep __log_buf System.map
将内核逻辑地址转换为 U - Boot 可理解的物理地址,然后使用 U - Boot 的
md
命令显示日志。
2. 性能分析与跟踪概述
2.1 性能分析的重要性
交互式调试虽能深入了解程序工作方式,但视野局限于小部分代码。要查看系统整体性能,需进行性能分析。程序员和系统设计师很难准确猜测瓶颈位置,因此出现性能问题时,应从系统整体入手,逐步使用更复杂的工具。
2.2 性能分析工具概述
- top 命令 :用于获取系统整体概况,常可将问题定位到单个程序。
- perf :Linux 性能分析器,可分析单个程序或获取更广泛的系统信息。
- Ftrace 和 LTTng :用于诊断内核相关问题,收集详细信息。
- Valgrind :具有沙盒执行环境,可监控程序运行并报告代码情况。
- strace :通过跟踪程序的系统调用揭示程序执行情况。
2.3 观察者效应
测量系统属性会影响观察结果,性能分析也不例外。每次系统观察都有 CPU 周期成本,测量工具还会影响缓存行为、占用内存和写入磁盘。因此,应尽量在目标上使用发布版本的软件、有效数据集并减少额外服务进行测量。
下面是一个简单的 mermaid 流程图,展示调试会话的主要步骤:
graph TD;
A[配置串口] --> B[启动 GDB];
B --> C[尝试连接 kgdb];
C --> D{连接成功?};
D -- 否 --> E[中断内核];
E --> C;
D -- 是 --> F[进行调试操作];
F --> G[结束调试, 禁用 kgdboc];
后续将详细介绍各种性能分析工具的使用方法。
3. 性能分析工具详解
3.1 使用 top 命令进行初步分析
top
命令是一个常用的系统监控工具,它可以实时显示系统中各个进程的资源使用情况,帮助我们快速定位可能存在性能问题的程序。以下是使用
top
命令的基本步骤:
1. 打开终端,输入
top
命令并回车。
2. 观察输出结果,重点关注以下几个指标:
-
%CPU
:进程占用 CPU 的百分比。
-
%MEM
:进程占用内存的百分比。
-
TIME+
:进程累计使用的 CPU 时间。
如果某个进程的 CPU 或内存占用率过高,那么它很可能就是性能问题的源头。
3.2 使用 perf 进行性能分析
perf
是 Linux 系统中强大的性能分析工具,它可以对系统和程序进行多方面的性能分析。以下是使用
perf
进行性能分析的常见场景和操作步骤:
3.2.1 分析单个程序的性能
如果怀疑某个程序存在性能问题,可以使用
perf
对其进行分析。例如,要分析
my_program
的性能,可以按照以下步骤操作:
1. 运行
perf record
命令记录程序的性能数据:
perf record ./my_program
- 分析记录的数据:
perf report
perf report
会显示程序中各个函数的调用情况和性能数据,帮助我们找出性能瓶颈。
3.2.2 分析系统整体性能
如果要对整个系统进行性能分析,可以使用
perf
的
-a
选项:
perf record -a sleep 10
上述命令会记录系统在 10 秒内的性能数据,然后可以使用
perf report
进行分析。
3.3 使用 Ftrace 和 LTTng 进行内核跟踪
Ftrace 和 LTTng 是两个用于内核跟踪的工具,它们可以帮助我们收集内核的详细信息,诊断内核相关的性能问题。
3.3.1 Ftrace
Ftrace 是 Linux 内核自带的跟踪工具,使用它可以跟踪内核中的各种事件。以下是使用 Ftrace 的基本步骤:
1. 启用 Ftrace:
echo function_graph > /sys/kernel/debug/tracing/current_tracer
- 开始跟踪:
echo 1 > /sys/kernel/debug/tracing/tracing_on
- 进行需要跟踪的操作,例如运行某个程序。
- 停止跟踪:
echo 0 > /sys/kernel/debug/tracing/tracing_on
- 查看跟踪结果:
cat /sys/kernel/debug/tracing/trace
3.3.2 LTTng
LTTng 是一个功能强大的跟踪工具,它可以提供更详细的跟踪信息。使用 LTTng 的基本步骤如下:
1. 安装 LTTng:
sudo apt-get install lttng-tools lttng-modules-dkms
- 创建会话:
lttng create my_session
- 启用跟踪事件:
lttng enable-event --kernel sched_switch
- 开始跟踪:
lttng start
- 进行需要跟踪的操作。
- 停止跟踪:
lttng stop
- 查看跟踪结果:
lttng view
3.4 使用 Valgrind 进行内存和代码分析
Valgrind 是一个用于内存调试、内存泄漏检测和性能分析的工具。它通过在沙盒环境中运行程序,监控程序的内存使用和代码执行情况。以下是使用 Valgrind 进行内存泄漏检测的示例:
valgrind --leak-check=full ./my_program
上述命令会运行
my_program
,并检查是否存在内存泄漏。如果存在内存泄漏,Valgrind 会输出详细的报告。
3.5 使用 strace 进行系统调用跟踪
strace
是一个用于跟踪程序系统调用的工具,它可以帮助我们了解程序在运行过程中与操作系统的交互情况。以下是使用
strace
的基本步骤:
1. 跟踪程序的系统调用:
strace ./my_program
- 输出结果会显示程序执行过程中调用的所有系统调用及其参数和返回值。
4. 总结
性能分析和跟踪是确保系统性能的重要手段。通过使用各种工具,我们可以从不同角度对系统和程序进行分析,找出性能瓶颈并进行优化。以下是本文介绍的工具总结:
| 工具名称 | 用途 |
| ---- | ---- |
| top | 快速定位系统中可能存在性能问题的程序 |
| perf | 对系统和程序进行多方面的性能分析 |
| Ftrace 和 LTTng | 收集内核的详细信息,诊断内核相关的性能问题 |
| Valgrind | 进行内存调试、内存泄漏检测和性能分析 |
| strace | 跟踪程序的系统调用,了解程序与操作系统的交互情况 |
下面是一个 mermaid 流程图,展示了性能分析的整体流程:
graph TD;
A[发现性能问题] --> B[使用 top 初步分析];
B --> C{问题定位到单个程序?};
C -- 是 --> D[使用 perf 分析单个程序];
C -- 否 --> E[使用 perf 分析系统整体性能];
D --> F{是否为内核问题?};
E --> F;
F -- 是 --> G[使用 Ftrace 或 LTTng 进行内核跟踪];
F -- 否 --> H[使用 Valgrind 进行内存和代码分析];
G --> I[优化内核代码];
H --> J[优化程序代码];
I --> K[再次进行性能分析];
J --> K;
K --> L{性能问题解决?};
L -- 是 --> M[结束];
L -- 否 --> B;
通过以上流程,我们可以不断优化系统和程序的性能,确保系统的稳定和高效运行。
超级会员免费看
1838

被折叠的 条评论
为什么被折叠?



