参考  http://www.cnblogs.com/honpey/p/4575928.html

kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工具,同时它又是其他一些更高级的内核调试工具(比如perf和systemtap)的“基础设施”,4.0版本的内核中,强大的eBPF特性也寄生于kprobe之上,所以kprobe在内核中的地位就可见一斑了。

kprobe是什么?

如何高效地调试内核?printk是一种方法,但是printk终归是毫无选择地全量输出,某些场景下不实用,于是你可以试一下tracepoint,我使能tracepoint机制的时候才输出。对于傻傻地放置printk来输出信息的方式,tracepoint是个进步,但是tracepoint只是内核在某些特定行为(比如进程切换)上部署的一些静态锚点,这些锚点并不一定是你需要的,所以你仍然需要自己部署tracepoint,重新编译内核。那么kprobe的出现就很有必要了,它可以在运行的内核中动态插入探测点,执行你预定义的操作。

kprobe怎么使用?

kprobe主要有两种使用方法,一是通过模块加载;二是通过debugfs接口。

模块加载的方式:内核源码下有目录下 samples/kprobes,该目录下有许多kprobes的例子,可以仿照这些例子写自己的kprobe模块。以kprobe_example.c为例,首先声明一个kprobe结构体,然后定义其中几个关键成员变量,包括symbol_name,pre_handler,post_handler。其中,symbol_name是函数名(kprobe_example.c中该项为do_fork),告诉内核我的探测点放置在了函数do_fork处,pre_hander和post_hander分别表示在执行探测点之前和之后执行的钩子函数。然后通过register_kprobe函数注册kprobe即可。将kprobe_example.ko inmod进内核之后,每当系统新启动一个进程,比如执行ls,cat等,都会输出:

pre_hander: p->addr = 0x***, ip = ****.

post_handler: p->addr = 0x***, pc = ****.

第一行是执行pre_handler钩子函数的输出,第二行是执行post_handler钩子函数的输出,当然这些都是内核中案例的写法,你可以写自己的钩子函数。

通过debugfs接口注册kprobe:模块加载的终究不是很方便,尤其对于一些不带gcc的嵌入式系统,需要交叉编译ko,将ko拷贝到单板,然后insmod,不便。debugfs下(确切地说,应该是ftrace)提供了一套注册、使能、注销kprobe的接口,可以很方便地操作kprobe。

用法如下:

  1) cd /sys/kernel/debug/tracing【有些系统没有挂载debugfs,需要先挂载下 mount -t debugfs nodev /sys/kernel/debug】

  2)进入到tracing目录,这里就是传说中ftrace的天下了,执行:

echo "p:sys_write_event sys_write" > kprobe_events    

向kprobe_events写入"p:sys_write sys_write",注册kprobe事件。你会发现,当前目录下的events下,新增一个kprobes目录,该目录下:

root@station:/sys/kernel/debug/tracing/events/kprobes# ls
enable filter sys_write_event

即,我们注册的kprobe事件生效了。那么"p:sys_write_event sys_write"是什么意思呢?首先p表示我们要注册一个kprobe,如果要注册retprobe,此处应为r;sys_write_event表示这个kprobe叫什么名字;sys_write表示我们的插入点在哪里。那么,“p:sys_write_event sys_write”的语义就很明显了:在函数sys_write处插入一个kprobe点,这个点的名字叫sys_write_event。

3)使能kprobe。执行:

cd /sys/kernel/debug/tracing/events/kprobes/events/sys_write_event
echo > enable
cd ../../.. 【退回到/sys/kernel/debug/tracing,查看trace文件的输出】
cat trace
trace文件的输出是如下的:
.....
   bash- [] d... 42715.347565: sys_write_event: (SyS_write+0x0/0xb0)    解释下置红的这条输出:pid为808的进程bash,在自本次开机42715.345565秒的时候,调用了一次函数sys_write。
.....

4)撤消kprobe。执行:

cd /sys/kernel/debug/tracing/events/kprobes/events/sys_write_event
echo > enable【首先先关闭kprobe】
cd ../../..
echo "-:kprobes/sys_write_event" >> kprobe_events 【注销kprobe】

以上就是kprobe的两种注册及使用方式:通过模块加载以及通过debugfs注册。这两种使用方法有什么联系?

使用模块加载的方式,是kprobe的一种原始用法:在kprobe结构体里定义插入点、钩子函数,然后通过register_kprobe注册上这个kprobe即可。ftrace接口是kprobe的一种应用,它是一套trace的框架,下面的trace机制包括tracepoint、function trace等,kprobe仅仅是这些trace机制中的一员。上面的讲述我们也已经看出来了,通过ftrace注册的kprobe的输出是在ftrace的输出:trace文件。模块加载模式中我们可以自定义kprobe的钩子函数pre_handler和post_handler,但是在ftrace下注册的kprobe的钩子是ftrace接口默认的,我们设置不了,但是具体输出什么,我们可以在echo “p:sys_write_event sys_write"时指定,比如指定x1寄存器的内容等,所以ftrace下注册的kprobe功能同样很强大。同时,由于ftrace下kprobe的输出基于ftrace的输出框架,所以输出信息包含当前进程、CPU、时间戳等信息,对于trace来说非常有用。

高级用法可以参看内核文档:kprobes.txt 以及 kprobetrace.txt。

kprobe原理解析的更多相关文章

  1. [转载] kprobe原理解析(一)

    From: https://www.cnblogs.com/honpey/p/4575928.html kprobe原理解析(一) kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工 ...

  2. kprobe原理解析(一)

    kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工具,同时它又是其他一些更高级的内核调试工具(比如perf和systemtap)的“基础设施”,4.0版本的内核中,强大的eBPF特性 ...

  3. kprobe原理解析(二)

    上一篇文章和大家简要说明了下kprobe到底应该怎样用,那么现在我们就揭开kprobe神秘的面纱,刨根问底,一睹kprobe的庐山真面目. kprobe的工作过程大致如下: 1)注册kprobe.注册 ...

  4. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  5. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  6. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  7. Web APi之过滤器创建过程原理解析【一】(十)

    前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...

  8. GeoHash原理解析

    GeoHash 核心原理解析       引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...

  9. alibaba-dexposed 原理解析

    alibaba-dexposed 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49821413 原理参考地址: htt ...

随机推荐

  1. 自然语言处理之word2vec

    在word2vec出现之前,自然语言处理经常把字词转为one-hot编码类型的词向量,这种方式虽然非常简单易懂,但是数据稀疏性非常高,维度很多,很容易造成维度灾难,尤其是在深度学习中:其次这种词向量中 ...

  2. WPF ListView点击删除某一行并获取绑定数据

    最近在开发WPF程序时遇到一个问题,在gridview中希望实现在每一行最后添加一个删除的按钮,但是发现点击每行的button时只会触发button的点击事件,并没有选中这一行,此时调用list.Se ...

  3. jupyter notebook中No module named 'tensorflow'

    当我们在jupyter notebook中运行时可能会遇见没有某个包的情况,如下: ---------------------------------------------------------- ...

  4. mount --bind使用方法

    我们可以通过mount --bind命令来将两个目录连接起来,mount --bind命令是将前一个目录挂载到后一个目录上,所有对后一个目录的访问其实都是对前一个目录的访问,如下所示: ## test ...

  5. shut immediate 数据库遭遇 ORA-24324 ORA-24323

    SQL> shut immediateORA-24324: service handle not initializedORA-24323: value not allowedORA-27140 ...

  6. Vue.js项目详解

    还是以Blog项目来讲解,最近我本人利用闲暇时间,以博客作为参考学习一些新的技术并尝试之前没有尝试过的思路来玩玩. 技术看似枯燥,但是带有一个目的来学,你会发现还是蛮有趣的. 主要实践的就是前后端分离 ...

  7. # 20175329 2018-2019-2 《Java程序设计》第二周学习总结

    # 学号 2018-2019-3<Java程序设计>第三周学习总结 ## 教材学习内容总结 第二三章与我们所学习的C语言有很多的相似点,在这里我想主要就以我所学习的效果来讨论一下JAVA与 ...

  8. docker+openvswitch实现主机与容器的网络通信

    主要用到openvswitch和netns网络名称空间的相关知识还有ip命令的使用. 实验环境的结构图如下: 思路如下: 安装openvswitch ovs创建br0,br1,并启动两个不加载网络的d ...

  9. 通过buildroot+qemu搭建ARM-Linux虚拟开发环境

    1. 配置工作环境 sudo apt install gcc build-essential bison flex gettext tcl sharutils libncurses-dev zlib1 ...

  10. [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子

    [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子 $ hdfs dfs -cat people.json {"name":&quo ...