跳转至

kprobe、uprobe、trancepoint、USDT

  • kprobe和uprobe分别是内核态和用户态下动态插桩技术
  • trancepoint、USDT分别是内核态和用户态静态跟踪技术
  • USDT:用户态预定义静态跟踪(user-level statically defined tracing)

1.1 kprobe

1. kprobes技术还有另外一个接口,即kretprobes,用来对内核函数返回时进行插桩以获取返回值。当用kprobes和kretprobes对同一个函数进行插桩时,可以使用时间戳来记录函数执行的时长。这在性能分析中是一个重要的指标。
2. kprobes可以对任何内核函数进行插桩,它还可以对函数内部的指令进行插桩。可以实时在生产环境系统中启用,不需要重启系统,也不需要以特殊方式重启内核。
  • kprobe:内核态探针,用于内核跟踪,提供了针对内核态动态插桩。
  • kretprobes:和kprobe相似,只是他在函数返回时触发,而kprobe在进入函数时触发。

1.2 uprobe

  • uprobe:用户态探针,用于用户程序跟踪,提供了针对用户态程序的动态插桩。
  • uretprobes:和uuprobe相似,只是他在函数返回时触发,而uprobe在进入函数时触发。
  • 可以通过perf命令动态插桩,随后,我们可以在/sys/kernel/debug/tracing/uprobe_events 文件中找到新插桩的uprobe事件
  • 示例
[root@centos7 perf_example]#  perf probe -x ./test for_loop
Added new event:
  probe_test:for_loop  (on for_loop in /root/perf_example/test)

You can now use it in all perf tools, such as:

        perf record -e probe_test:for_loop -aR sleep 1

[root@centos7 perf_example]# cat /sys/kernel/debug/tracing/uprobe_events 
p:probe_test/for_loop /root/perf_example/test:0x000000000000064d

1.3 tracepoint

查看系统支持的tracepoint?
1. 可以在/sys/kernel/debug/tracing/events 目录下查看
2. `perf list tracepoint` 命令查看
  • tracepoints: 跟踪点可以用来对内核进行静态插桩。内核开发者在内核函数中的特定逻辑位置处,有意放置了这些插桩点;然后这些跟踪点会被编译到内核的二进制文件中。
  • tracepoints格式:subsystem:eventname(子系统:事件名)比如kmem:kmalloc
  • 示例
[root@centos7 events]# ll /sys/kernel/debug/tracing/events
total 0
drwxr-x---.   6 root root 0 Aug 18 22:29 alarmtimer
drwxr-x---.   3 root root 0 Aug 18 22:29 avc
drwxr-x---.  21 root root 0 Aug 18 22:29 block
drwxr-x---.   3 root root 0 Aug 18 22:29 bpf_test_run
drwxr-x---.   3 root root 0 Aug 18 22:29 bpf_trace
drwxr-x---.   6 root root 0 Aug 18 22:29 bridge
drwxr-x---.  15 root root 0 Aug 18 22:29 cgroup
...省略...
[root@centos7 events]# perf list tracepoint

List of pre-defined events (to be used in -e):

  alarmtimer:alarmtimer_cancel                       [Tracepoint event]
  alarmtimer:alarmtimer_fired                        [Tracepoint event]
  alarmtimer:alarmtimer_start                        [Tracepoint event]
  alarmtimer:alarmtimer_suspend                      [Tracepoint event]
  avc:selinux_audited                                [Tracepoint event]
  block:block_bio_backmerge                          [Tracepoint event]
  block:block_bio_bounce                             [Tracepoint event]
  block:block_bio_complete                           [Tracepoint event]
...省略...

1.4 USDT

USDT是随sun公司的DTrace工具火起来的,现在己经被多种应用程序支持了。Linux对USDT的支持,最早来自SystemTap项目的跟踪器。BCC和bpftrace跟踪工具建立在上述工作基础之上,两者都支持USDT。
  • USDT:用户态预定义静态跟踪(user-level statically defined tracing,USDT)提供了一个用户空间版的跟踪点机制。USDT与众不同之处在于,它依赖于外部的系统跟踪器来唤起。如果没有外部跟踪器,应用中的USDT点不会做任何事,也不会开启。

1.4.1 自定义USDT

  • 给应用程序添加USDT探针,有两种方式可选:
    • 通过systemtap-sdt-dev包提供的头文件和工具,
    • 或者使用自定义的头文件。 这些探针定义了可以被放置在代码中各个逻辑位置上的宏,以此生成USDT的探针。在BCC项目的examples/usdt-sample目录下包含了USDT示例

1.5 tracepoints和kprobe比较

  1. 对内核开发者来说,跟踪点有一定的维护成本,而且它的使用范围比kprobes要窄得多。
  2. 使用跟踪点的主要优势是它的API比较稳定:基于跟踪点的工具,在内核版本升级后一般仍然可以正常工作。而基于kprobes的工具在内核版本升级时,如果被跟踪的函数被重命名或者功能改变,则会导致其不可用。如果条件允许,你应当优先尝试使用跟踪点,只有在条件不满足时才使用kprobes作为替代。