kprobe是linux kernel提供的一种动态调试机制,可以在不修改内核源码,不中断系统运行的情况下,插入探针(probe)到内核函数或指令处,以便在该位置执行时获取运行信息,调试或收集性能数据。

Kprobe类型

        kprobe实现了三种类型的探测点:

  • kprobes:可以被插入到内核的任何指令为止的探测点
  • jprobes:只能被插入到内核函数的入口,该功能已弃用
  • kretprobes:在指定的内核函数返回时才被执行

Kprobe是如何工作的

       kernel通过动态修改被探测函数(目标函数)的指令,将其替换为断点指令,从而将执行流从目标函数强制转向预定义的处理函数(kprobe)。

  • 具体执行流程:当Kprobe被注册时,kprobes会复制并验证 被探测对象(目标函数)的第一条指令(第一个字节,复制内容保存在kprobe结构体内私有区域),并将其替换成断点指令(该断点指令关联kprobe实例),当断点命中(执行到目标函数时,触发断点异常int3: do_int3),CPU会暂停当前正常工作流程,并通过notifier_call_chain机制把控制权转交给kprobe,找到对应的kprobe实例,从而执行对应的pre_handler 。执行完成后,kprobe会将CPU指针指向之前复制的目标函数的原始指令地址上,并单步执行(真正执行目标函数),单步执行后,kprobe再次陷入单步异常(int1),int1处理(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 documentation

KProbes [LWN.net] 介绍

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐