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