内核态调测工具(一) kprobe

本文详细介绍了Linux内核的kprobe调试工具,包括kprobe、jprobe和kretprobe的功能与使用方法,以及如何注册和取消注册探针。此外,还提到了kprobe的用户态接口和配置选项,帮助用户更深入地了解和利用kprobe进行内核行为跟踪。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Kprobe介绍

Kprobe是一种内核调测手段,它可以动态地跟踪内核的行为、收集debug信息和性能信息。可以跟踪内核几乎所有的代码地址(almost:不允许跟踪的名单blacklist在/sys/kernel/debug/kprobes/blacklist),并且当断点被击中后会响应处理函数。

Kprobe有三个子功能:
Kprobes:几乎可以插入内核的任何指令;
Jprobes:可以插入内核的某个函数;
Kretprobes(return probes):可以在函数返回时触发;
这三个子功能,可以让用户在内核指令、内核进入函数和从函数退出时进行断点处理。

框架支持

Kprobes and return probes are implemented on the following
architectures:

  • i386 (Supports jump optimization)
  • x86_64 (AMD-64, EM64T) (Supports jump optimization)
  • ppc64
  • ia64 (Does not support probes on instruction slot1.)
  • sparc64 (Return probes not yet implemented.)
  • arm
  • ppc
  • mips
  • s390

控制接口说明

/sys/kernel/debug/kprobes/list: 列出内核中已经设置kprobe断点的函数
/sys/kernel/debug/kprobes/enabled: kprobe开启/关闭开关
/sys/kernel/debug/kprobes/blacklist: kprobe黑名单(无法设置断点函数)
/proc/sys/debug/kprobes-optimization: Turn kprobes optimization ON/OFF.

Kprobe函数接口及使用

1.Jprobe使用

#include <linux/kprobes.h>
int register_jprobe(struct jprobe *jp)
void unregister_jprobe(struct jprobe *jp);

1) register_jprobe()是jprobe的注册函数,参数jp->kp.addr指向需要调测的函数。
2) 当内核调用函数时断点被触发,执行jp->entry指向的处理函数。
3) 其中jp->kp.addr指向的函数名(以内核do_fork()函数为例),可以按以下方式确认内核是否存在:
grep do_fork /usr/src/linux/System.map
nm vmlinuz |grep do_fork
cat /proc/kallsyms |grep do_fork
kallsyms_lookup_name(“do_fork”);
4) jprobe断点的取消注册,调用unregister_jprobe()。

在linux内核源码中提供了jprobe的用例
samples/kprobes/jprobe_example.c:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>

// 断点触发后的处理函数,这里打印stack信息,然后调用jprobe_return()返回断点触发位置
static long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
              unsigned long stack_size, int __user *parent_tidptr,
              int __user *child_tidptr)
{
        pr_info("jprobe: clone_flags = 0x%lx, stack_start = 0x%lx "
                "stack_size = 0x%lx\n", clone_flags, stack_start, stack_size);

        /* Always end with a call to jprobe_return(). */
        jprobe_return();
        return 0;
}

// jprobe结构体初始化,其中.entry指定处理函数,.kp指定打断点的函数名称
static struct jprobe my_jprobe = {
        .entry                  = jdo_fork,
        .kp = {
                .symbol_name    = "do_fork",
        },
};

// 模块init函数,inmode插入模块从这里开始执行
static int __init jprobe_init(void)
{
        int ret;

        //jprobe注册函数
        ret = register_jprobe(&my_jprobe);
        if (ret < 0) {
                printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
                return -1;
        }
        printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
               my_jprobe.kp.addr, my_jprobe.entry);
        return 0;
}

// 模块exit函数,rmmod卸载模块执行这个函数
static void __exit jprobe_exit(void)
{
        //取消jprobe断点
        unregister_jprobe(&my_jprobe);
        printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr);
}

module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");

2.Kprobe使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello小崔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值