土法炼钢兴趣小组的算法知识备份

【操作系统百科】kprobe、uprobe 与 fprobe

文章导航

分类入口
os
标签入口
#kprobe#uprobe#fprobe#usdt#dynamic-tracing

目录

动态探针让你在任意内核/用户函数上挂钩——不需要重新编译,不需要重启。

一、先看图

flowchart TD
    KPROBE[kprobe<br/>内核函数探针] --> INT3[int3 断点<br/>或 ftrace]
    UPROBE[uprobe<br/>用户态探针] --> BKPT[断点指令<br/>替换用户代码]
    FPROBE[fprobe<br/>基于 ftrace] --> FTRACE[ftrace 框架<br/>批量高效]

    INT3 --> HANDLER[回调函数<br/>或 BPF 程序]
    BKPT --> HANDLER
    FTRACE --> HANDLER

    classDef kern fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef user fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    class KPROBE,INT3,FPROBE,FTRACE kern
    class UPROBE,BKPT user
    class HANDLER kern

二、kprobe

2.1 原理

  1. 保存目标地址的原始指令
  2. 替换为 int3(x86)断点
  3. 触发时 → 执行 pre_handler → 单步执行原始指令 → 执行 post_handler

2.2 使用

# 通过 tracefs
echo 'p:myprobe do_sys_openat2 filename=+0(%si):string' > \
    /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
cat /sys/kernel/debug/tracing/trace

2.3 kretprobe

echo 'r:myret do_sys_openat2 $retval' > \
    /sys/kernel/debug/tracing/kprobe_events

捕获函数返回值 → 通过替换返回地址实现。

三、fprobe(推荐)

基于 ftrace → 不需要 int3 → 更高效:

struct fprobe fp = {
    .entry_handler = my_handler,
};
register_fprobe(&fp, "do_sys_openat2", NULL);

fprobe 支持批量注册 → 适合 BPF 大规模追踪。

四、uprobe

4.1 原理

  1. 在 ELF 文件中找到目标函数偏移
  2. 运行时替换为断点指令
  3. 触发时 → 陷入内核 → 执行回调 → 恢复

4.2 使用

echo 'p:myuprobe /usr/lib/libc.so.6:malloc size=%di' > \
    /sys/kernel/debug/tracing/uprobe_events
echo 1 > /sys/kernel/debug/tracing/events/uprobes/myuprobe/enable

4.3 USDT

User Statically-Defined Tracing → 应用程序预埋探针:

bpftrace -e 'usdt:/usr/lib/libc.so.6:memory_malloc_retry { printf("retry\n"); }'

五、BPF 联动

SEC("kprobe/do_sys_openat2")
int BPF_KPROBE(trace_open, int dfd, struct filename *name)
{
    bpf_printk("open: %s\n", name->name);
    return 0;
}

BPF + kprobe/uprobe 是最常用的动态追踪组合。

六、性能开销

探针类型 单次开销(x86_64)
kprobe (int3) ~100-200ns
fprobe (ftrace) ~30-50ns
uprobe ~1-3μs
tracepoint ~50-100ns

uprobe 开销最高 → 涉及用户态/内核态切换。

七、安全限制

# 非 root 用户限制
sysctl kernel.perf_event_paranoid=2     # 限制 perf
sysctl kernel.kptr_restrict=1           # 隐藏内核指针

lockdown 模式 → kprobe 可能被禁用。

八、常见陷阱

九、观察

cat /sys/kernel/debug/kprobes/list      # 已注册 kprobe
cat /sys/kernel/debug/tracing/uprobe_events

# bpftrace 示例
bpftrace -e 'kprobe:vfs_read { @[comm] = count(); }'
bpftrace -e 'kretprobe:vfs_read { @bytes = hist(retval); }'
bpftrace -e 'uprobe:/usr/bin/bash:readline { printf("readline\n"); }'

十、小结


参考文献

工具


上一篇eBPF 核心 下一篇kdump 与 crash

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-05-06 · os

【操作系统百科】内核内存调试

内核内存 bug 是最难追的:UAF、OOB、double free、leak 都可能沉默数月。本文讲 KASAN 三种模式、KFENCE 生产采样、kmemleak、SLUB_DEBUG、UBSAN/KCSAN 联动。

2026-05-08 · os

【操作系统百科】VFS 四层抽象

Linux 的一切皆文件靠 VFS 实现——superblock、inode、dentry、file 四层抽象加 ops 表。本文讲 VFS 核心数据结构、dcache、inode cache、RCU lookup,以及文件系统如何插入 VFS。

2026-04-22 · os

操作系统百科

Linux 6.x 视角下的操作系统系列索引:110 篇覆盖调度、虚拟内存、文件系统与 I/O、并发、隔离、可观测性,按主题、阅读路径与关键问题三种入口组织。

2026-05-27 · os

【操作系统百科】用户态分配器:jemalloc vs tcmalloc

jemalloc 与 tcmalloc 都想解决多线程分配器的老问题:锁争抢、碎片、RSS 膨胀与回收抖动。但两者把优化重点放在了不同位置:tcmalloc 更激进地把热路径推到 per-CPU,jemalloc 则把 arena、extent、decay 和 profiling 做成了一套更完整的内存治理工具箱。


By .