(此文主要用来记录一些调试,性能测试与分析等工具的用法,备忘)

Linux下的追踪和性能统计

Linux内核提供的基础设施

  • tarcepoints => 静态探测点
  • kprobe => 内核态动态探测点(kernel/kprobe.c, example:sample/kprobe)
  • uprobe => 用户态动态探测点(kernel/events/uprobe.c)

其最基本的用法我们可以写内核模块注入某个探测点的探针,做一些追踪与统计分析,
但通常会有更方便的框架以及其前端工具,比如下面将提到的ftrace与trace-cmd,
perf_events与perf, systemtap, 还有基于这些前端工具的工具perf-tools…

ftrace framework

1. 介绍

ftrace框架主要以debugfs中/sys/kernel/debug/trace文件系统的形式提供了静态和动态
追踪的接口,ftrace框架有命令行和图像化的前端工具trace-cmd 和 kernelshark。而且
提供了不同种类的tracer, 可以使用下面命令查看:

cat /sys/kernel/debug/trace/available_tracers

ftrace的核心代码位于kernel/trace目录下,ftrace.c注册了debugfs下的trace目录,
trace_kprobe.c和trace_uprobe.c提供了kprobe和uprobe的接口。除了kprobe和uprobe,
ftrace还提供了events支持,主要位于/kernel/sys/debug/trace/events, 主要包括
硬件事件,内核软件事件,以及静态tracepoints的事件。可以通过下面命令查看支持的事件:

cat /sys/kernel/debug/trace/available_events

2. 例子

(例子来源于内核源码Documentation/trace)

  • 基于ftrace使用kprobe动态trace:
// 添加探针
echo 'p:myprobe do_sys_open dfd=%ax filename=%dx flags=%cx mode=+4($stack)' > /sys/kernel/debug/tracing/kprobe_events
echo 'r:myretprobe do_sys_open $retval' >> /sys/kernel/debug/tracing/kprobe_events

// 激活
echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/myretprobe/enable

// 查看输出
cat /sys/kernel/debug/tracing/trace

// 关闭
echo 0 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
echo 0 > /sys/kernel/debug/tracing/events/kprobes/myretprobe/enable

// 移除探针
echo -:myprobe >> kprobe_events
echo > /sys/kernel/debug/tracing/kprobe_events
  • 基于ftrace使用uprobe动态trace(kernel/trace/trace_uprobe.c)
// 添加探针
echo 'p: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
echo 'r: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events

// 激活
echo 1 > events/uprobes/enable

// 查看输出
cat /sys/kernel/debug/tracing/trace

// 关闭
echo 0 > events/uprobes/enable

// 移除
echo '-:bash_0x4245c0' >> /sys/kernel/debug/tracing/uprobe_events
echo > /sys/kernel/debug/tracing/uprobe_events
  • 基于ftrace使用tracepoints静态events(kernel/trace/trace_events.c)
    • 通常我们可以写内核模块给某个静态tracepoint添加探针
    • 基于ftrace events
// 添加event
echo sched_wakeup >> /sys/kernel/debug/tracing/set_event
echo *:* > /sys/kernel/debug/tracing/set_event
echo 'irq:*' > /sys/kernel/debug/tracing/set_event

// 激活event
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable

// 查看输出
cat /sys/kernel/debug/tracing/trace

// 移除event
echo '!sched_wakeup' >> /sys/kernel/debug/tracing/set_event
echo > /sys/kernel/debug/tracing/set_event

perf_events

1. 介绍

perf_events和对应的前端工具perf提供了硬件和软件层面的计数等性能分析。其源码位于
内核源码树tools/perf目录下。

2. 例子

systemtap

1. 介绍
2. 例子

perf-tools and flamegraph

1. 介绍
2. 例子

GDB常用调试命令和调试技巧

命令
  • status
    • info => 查看程序本身相关信息
      • args => 打印参数
      • breakpoints => 断点信息
      • files => 进程的地址空间详细内容
      • sharedlibrary => 加载的共享库
      • frame => 栈帧
      • line => 当前所在行
      • locals => 当前栈帧中的变量
      • registers => 寄存器信息
      • stack => 栈信息
      • source => 当前源码文件信息
      • auxv => 进程属性
      • address/symbol => symbol的地址/地址的symbol
      • threads => 线程信息
      • tracepoints => tracepoint信息
      • vtbl => 某个类指针的虚函数表
      • watchpoints => 显示watchpoints信息
    • show => 查看系统配置环境等信息
      • environment => 环境变量
      • endian => 大小端
      • print => 打印格式的相关配置
  • breakpoints
    • awatch/watch => 为某个表达式设置watchpoint
    • break => 设置断点
    • clear => 清除断点
    • catch => 当发生下列某个时间时stop
      • assert
      • catch
      • fork
      • exec
      • signal
      • syscall
      • throw
      • vfork
    • delete => 删除
      • breakpoints
      • checkpoint
      • tracepoints
  • data

    • disassemble => 反汇编某段代码
    • dump binary
      • memory => 二进制形式dump内存
      • value => 二进制形式dump值
    • set => 修改gdb配置
  • stack

    • backtrace/bt => 所有栈帧
    • down/up => 下一帧/上一帧
    • frame => 打印某一帧
技巧
  • 设置watch points调试内存非法写等错误

valgrind常用命令和技巧

命令
  • –tool
    • memcheck =>
    • cachegrind =>
    • callgrind =>
    • helgrind =>
  • –trace-children => 多进程
  • –leak-check=no|summay|yes|full => 打印内存泄露信息
技巧
  • 生成调用图
    • 先用valgrind生成call.grind.out.xxx文件
    • 生成dot文件: gprof2dot -f callgrind -n10 -s callgrind.out.xxx > out.dot
    • 生成png: dot -Tpng out.dot -o out.png
Logo

更多推荐