Linux kernel debug trace: Kprobe

发布时间:2026/7/27 9:41:40

Linux kernel debug  trace: Kprobe kprobe是linux kernel提供的一种动态调试机制可以在不修改内核源码不中断系统运行的情况下插入探针probe到内核函数或指令处以便在该位置执行时获取运行信息调试或收集性能数据。Kprobe类型kprobe实现了三种类型的探测点kprobes可以被插入到内核的任何指令为止的探测点jprobes只能被插入到内核函数的入口该功能已弃用kretprobes在指定的内核函数返回时才被执行Kprobe是如何工作的kernel通过动态修改被探测函数目标函数的指令将其替换为断点指令从而将执行流从目标函数强制转向预定义的处理函数kprobe。具体执行流程当Kprobe被注册时kprobes会复制并验证 被探测对象目标函数的第一条指令第一个字节复制内容保存在kprobe结构体内私有区域并将其替换成断点指令该断点指令关联kprobe实例当断点命中执行到目标函数时触发断点异常int3: do_int3CPU会暂停当前正常工作流程并通过notifier_call_chain机制把控制权转交给kprobe找到对应的kprobe实例从而执行对应的pre_handler。执行完成后kprobe会将CPU指针指向之前复制的目标函数的原始指令地址上并单步执行真正执行目标函数单步执行后kprobe再次陷入单步异常int1int1处理(do_debug) 中会调用post_handler, 并从单步模式恢复到正常模式然后返回目标函数中断指令之后的位置继续正常执行。断点指令关联kprobe实例kernel有一个全局的哈希表它以被探测的地址为键kprobe注册时会将kprobe实例插入到这个哈希表中。当执行到目标函数时由于目标函数首指令被替换成断点指令会触发断点异常异常处理程序会检查触发异常的地址并对照内核kprobe哈希表查找从而找到kprobe实例。Kprobes的特性与局限性kprobe允许在同一个地址进行多个探测且存在post_handler的探针点无法被优化。如果为内联函数注册探测点kprobe无法保证对内联函数的所有实例都注册探测点因为gcc可能隐式地内联一个函数。若探测处理函数调用了另一个探测点则该探测点的处理函数将不运行但其kprobe.nmissed会加1多个kprobe handler 或同一个函数的多个kprobe实例可以同时运行在不同的CPU上。除了注册和卸载时kprobe不能使用mutex或分配内存code 示例#include linux/kernel.h #include linux/module.h #include linux/kprobes.h static struct kprobe kp; // 目标函数执行时会进入这个回调 static int handler_pre(struct kprobe *p, struct pt_regs *regs) { pr_info(kprobe hit: function%s, ip%p\n, p-symbol_name, p-addr); return 0; } static int __init kprobe_init(void) { kp.symbol_name do_fork; // 目标函数例如 do_fork kp.pre_handler handler_pre; /* 注册kprobe */ if (register_kprobe(kp) 0) { pr_err(register_kprobe failed\n); return -1; } pr_info(kprobe registered for %s\n, kp.symbol_name); return 0; } static void __exit kprobe_exit(void) { unregister_kprobe(kp); pr_info(kprobe unregistered\n); } module_init(kprobe_init) module_exit(kprobe_exit) MODULE_LICENSE(GPL);参考[monitor] 8. Linux kprobe(内核探针)-CSDN博客Kernel Probes (Kprobes) — The Linux Kernel documentationKProbes [LWN.net] 介绍

相关新闻