kprobe:https://docs.kernel.org/trace/kprobes.html
wprobes:https://lwn.net/Articles/1037390/
要理解 kprobe 和 wprobes 是什么、有啥区别,我们可以从“核心定位、监控目标、使用场景、工作方式”四个维度拆解,结合内核调试的实际需求对比分析,最后用表格总结关键差异,帮你快速理清逻辑。
kprobe 是 Linux 内核最基础、最核心的 动态调试工具,属于“轻量级插桩技术”,也是 perf、SystemTap、BPF 等高级工具的底层依赖。它的核心作用是跟踪内核指令执行,帮开发者在不中断内核运行的情况下,收集函数调用、参数、返回值等上下文信息。
do_page_fault 等),支持函数入口、函数中间某行代码、指定内存地址。pre_handler(指令执行前回调)、post_handler(指令执行后回调)。vfs_read 被调用的次数、传入的参数(如读取的文件句柄、缓冲区地址)。register_kprobe() 时,kprobe 会先复制目标指令的字节(避免破坏原代码),再把原指令首字节替换为断点指令(如 int3)。pre_handler(比如打印参数),再单步执行复制的原指令(避免移除断点导致其他 CPU 漏探测),最后运行 post_handler(可选)。wprobes 是 kprobe 子系统的新增功能(2025 年提交的补丁),本质是“内核版的观察点(watchpoint)”,核心作用是监控内存访问——当指定内存区域被“读/写”时触发回调,帮开发者定位“谁篡改了内存”这类难题。
jiffies、slab 分配的动态内存),支持监控“读(r)”“写(w)”“读写(rw)”三种操作。/sys/kernel/tracing/dynamic_events 文件写入字符串即可创建监控,比如监控 jiffies 的写入操作:
# 进入 tracing 目录
cd /sys/kernel/tracing
# 创建监控:名称 my_jiffies,监控 jiffies(8字节)的写操作,打印写入值
echo 'w:my_jiffies w@jiffies:8 value=+0($addr)' >> dynamic_events
# 启用监控
echo 1 > events/wprobes/my_jiffies/enable
用表格对比最清晰,从 6 个关键维度拆解:
| 对比维度 | kprobe(普通/返回探针) | wprobes(内存观察点) |
|---|---|---|
| 核心定位 | 跟踪内核指令执行(函数调用、指令执行时机) | 监控内存访问行为(读/写/读写操作) |
| 监控目标 | 指令地址(函数入口、中间代码、指定内存地址) | 内存区域(固定变量、动态分配内存,需指定长度) |
| 触发条件 | CPU 执行到目标指令时触发 | 对目标内存执行“读/写/读写”操作时触发 |
| 配置复杂度 | 需写内核模块(调用 register_kprobe() 等 API),或用 /sys/kernel/tracing/kprobe_events 配置 |
无需写代码,直接向 /sys/kernel/tracing/dynamic_events 写入字符串配置 |
| 典型使用场景 | 1. 分析函数调用参数、返回值<br>2. 计算函数执行耗时<br>3. 跟踪指令执行流程 |
1. 定位内存篡改源头(如变量被意外修改)<br>2. 监控动态内存生命周期(如 slab 分配的内存)<br>3. 检测内存越界访问 |
| 底层依赖 | 独立实现(断点指令 + 单步执行) | 依赖 kprobe 子系统的陷阱处理逻辑,专注内存监控 |
vfs_read、执行耗时多久)→ 用 kprobe/kretprobe;jiffies 被哪个代码写了、slab 内存被越界访问)→ 用 wprobes。简单说:kprobe 盯“代码执行”,wprobes 盯“内存访问”,二者互补,都是内核调试的核心工具。