You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EBPF是否只能通过kprobe实现Linux内核函数的监控?

监控Linux内核函数的BPF方法不止kprobe

当然不是只能用kprobe来监控任意内核函数,除了kprobe,还有几种BPF追踪技术可以实现内核函数监控,以下是常见的几种:

1. kretprobe

和kprobe配套使用,专门用来监控内核函数的返回阶段,可以获取函数的返回值。kprobe监控函数入口,kretprobe监控函数出口,两者结合能完整覆盖函数的执行周期。

用BCC实现的简单示例:

#!/usr/bin/python3
from bcc import BPF
from time import sleep

bpf_program = """
int test_kretprobe(void *ctx) {
    // 通过PT_REGS_RC获取函数返回值
    int ret_val = PT_REGS_RC(ctx);
    bpf_trace_printk("getpid返回值: %d\\n", ret_val);
    return 0;
}
"""

b = BPF(text=bpf_program)
b.attach_kretprobe(event="__x64_sys_getpid", fn_name="test_kretprobe")

while 1:
    sleep(10)
    b.trace_print()

2. fentry/fexit

这是Linux 5.5版本引入的高效追踪机制,直接在内核函数的入口/出口位置插入BPF程序,不需要像kprobe那样依赖断点指令,性能损耗更低,同时避免了kprobe可能存在的某些稳定性问题。

需要注意的是,使用fentry/fexit要求内核版本≥5.5,BCC中可以通过attach_fentry和attach_fexit方法实现:

#!/usr/bin/python3
from bcc import BPF
from time import sleep

bpf_program = """
int test_fentry(void *ctx) {
    bpf_trace_printk("进入getpid函数\\n");
    return 0;
}
"""

b = BPF(text=bpf_program)
b.attach_fentry(event="__x64_sys_getpid", fn_name="test_fentry")

while 1:
    sleep(10)
    b.trace_print()

3. Tracepoints

内核预定义的追踪点,属于稳定的官方接口,不会因为内核版本迭代导致函数名、参数结构变化。但tracepoints是内核预先定义好的,只能监控那些内核提供了追踪点的函数,无法覆盖所有内核函数。

比如监控系统调用入口的tracepoint示例:

#!/usr/bin/python3
from bcc import BPF
from time import sleep

bpf_program = """
int test_tracepoint(void *ctx) {
    bpf_trace_printk("触发getpid系统调用\\n");
    return 0;
}
"""

b = BPF(text=bpf_program)
# 绑定sys_enter_getpid追踪点
b.attach_tracepoint(tp="syscalls:sys_enter_getpid", fn_name="test_tracepoint")

while 1:
    sleep(10)
    b.trace_print()

总结

如果需要监控任意内核函数,kprobe/kretprobe、fentry/fexit是更合适的选择——它们可以作用于所有导出的内核函数(非导出函数虽然也能通过地址绑定,但稳定性差,不推荐)。而tracepoints适合对稳定性要求高,但不需要覆盖所有函数的场景。

内容的提问来源于stack exchange,提问作者ray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:01:53