查看是否启动

一、kprobe简介

kprobe是一个动态地收集调试和性能信息的工具,它从Dprobe项目派生而来,是一种非破坏性工具,用户用它几乎可以跟踪任何函数或被执行的指令以及一些异步事件(如timer)。它的基本工作机制是:用户指定一个探测点,并把一个用户定义的处理函数关联到该探测点,当内核执行到该探测点时,相应的关联函数被执行,然后继续执行正常的代码路径。

kprobe实现了三种类型的探测点: kprobes, jprobes和kretprobes (也叫返回探测点)。 kprobes是可以被插入到内核的任何指令位置的探测点,jprobes则只能被插入到一个内核函数的入口,而kretprobes则是在指定的内核函数返回时才被执行。

一般,使用kprobe的程序实现作一个内核模块,模块的初始化函数来负责安装探测点,退出函数卸载那些被安装的探测点。kprobe提供了接口函数(APIs)来安装或卸载探测点。

二、kprobe实现原理

当安装一个kprobes探测点时,kprobe首先备份被探测的指令,然后使用断点指令(即在i386和x86_64的int3指令)来取代被探测指令的头一个或几个字节。当CPU执行到探测点时,将因运行断点指令而执行trap操作,那将导致保存CPU的寄存器,调用相应的trap处理函数,而trap处理函数将调用相应的notifier_call_chain(内核中一种异步工作机制)中注册的所有notifier函数,kprobe正是通过向trap对应的notifier_call_chain注册关联到探测点的处理函数来实现探测处理的。当kprobe注册的notifier被执行时,它首先执行关联到探测点的pre_handler函数,并把相应的kprobe struct和保存的寄存器作为该函数的参数,接着,kprobe单步执行被探测指令的备份,最后,kprobe执行post_handler。等所有这些运行完毕后,紧跟在被探测指令后的指令流将被正常执行。

三、kprobe的接口函数

1. kprobe的注册与解除函数

2. kprobe结构体

函数的查找

必须启用 CONFIG_KALLSYMS 编译内核

一个探测点处理函数能够修改被探测函数的上下文,如修改内核数据结构,寄存器等。因此,kprobe可以用来安装bug解决代码或注入一些错误或测试代码。

其中pre_handler与post_handler的函数原型,如下:

寄存器结构体(以32位的系统为例):

寄存器的修改:

堆栈的修改:

参考: https://www.kernel.org/doc/Documentation/kprobes.txt