kprobe API: 如register_kprobe()等 基于Frace的,通过/sys/kernel/debug/tracing/kprobe_events:通过向这个文件写入字符串,可以配置开启和停止kprobes perf_event_open(): 与perf工具所使用的一样,现在BPF跟踪工具也开始使用这些函数 通过strace可以看到这里是使用perf_event_open()接口来和kprobe打交道。 kprobe工作...
int register_kprobes(struct kprobe **kps, int num) //注册探测函数向量,包含多个探测点 void unregister_kprobes(struct kprobe **kps, int num) //卸载探测函数向量,包含多个探测点 int disable_kprobe(struct kprobe *kp) //临时暂停指定探测点的探测 int enable_kprobe(struct kprobe *kp) //恢复指定探...
大部BPF程序都是这一类,主要通过kprobe、tracepoint(rawtracepoint)等追踪系统行为及获取系统硬件信息。也可以访问特定程序的内存区域,从运行进程中提取执行跟踪信息。网络 这类BPF程序用于检测和控制系统的网络流量。可以对网络接口数据包进行过滤,甚至可以完全拒绝数据包。用户态是通过系统调用来加载BPF程序到内核的,...
kprobe程序允许在执行内核函数之前插入BPF程序。当内核执行到kprobe挂载的内核函数时,先运行BPF程序,BPF程序运行结束后,返回继续开始执行内核函数。下面是一个使用kprobe的bcc程序示例,功能是监控内核函数kfree_skb函数,当此函数触发时,记录触发它的进程pid,进程名字和触发次数,并打印出触发此函数的进程pid,进程名字和触发...
int kprobe__sys_nanosleep(void *ctx) { struct { u64 ts; } data = {bpf_ktime_get_ns()}; events.perf_submit(ctx, &data, sizeof(data)); return 0; } """b = BPF(text=text) b["events"].open_perf_buffer(cb) time.sleep(0.1) ...
用户态是通过系统调用来加载BPF程序到内核的,在加载程序时,需要传递的参数中有一个字段叫prog_type,这个就是BPF的程序类型,跟踪相关的是:BPF_PROG_TYPE_KPROBE和BPF_PROG_TYPE_TRACEPOINT,网络相关是:BPF_PROG_TYPE_SK_SKB、BPF_PROG_TYPE_SOCK_OPS等。下面是描述BPF程序类型的枚举结构: ...
BPF代码,即内核事件发生时候调用的代码,下图中的bpf_prog.c,通过LLVM和clang编译器,将代码转成BPF字节码。 加载BPF代码的用户代码,即负责进行系统调用将编写的BPF代码编译后的字节码,加载到内核中探针上(kprobe)。 用户程序通过读取映射表内容,来获取BPF代码的输出,即bpf_prog.c这个模块输出。
当函数入口被 kprobe 命中是, 将函数返回地址保存并替换为一个“蹦床”(tram-poline)函数地址. 当函数最终返回时,CPU 将控制权交给蹦床函数处理. 在kretprobe 处理完成之后在返回到之前保存的地址. 当不再需要 kretprobe 时, 函数入口的 krobe 和 kretprobe 处理函数就被移除了. ...
遍历bpf程序(函数如kprobe_vfs_read)指令集合prog->insnsi[],调用build_insn进行指令的jit编译 5、还原堆栈build_epilogue 1) 当前指针减去stack_size,将是BPF fp register的地方(前面build_prologue我们报错寄存器的尾部) 2) 依次弹出刚才我们保存的寄存器,tcc、r9/r8/r7/r6、FP/LR ...
内核中的 kprobe_example.c 与 kretprobe_example.c 代码逻辑很简单,主要流程就是注册需要探测的函数监测点struct kprobe kp,然后register_kprobe(&kp),当加载内核模块时就可以探测。 比如kprobe_example 用于获取内核在调用"kernel_clone()" 函数时的栈追踪和选择的寄存器地址等信息 ...