参考  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. 通过JS如何获取IP地址

    通过JS获取你真实的外网IP和内网IP,就算开代理也没有用,想想真是太可怕了,还能不能愉快的装逼了! 代码: //get the IP addresses associated with an acc ...

  2. 3、原生jdbc链接数据库之锁与事务

    一.锁的概念1.作用:是保证数据的一致性,只能一个人修改数据,不能同时多用户修改2.分类:行级锁和表级锁   乐观锁和悲观锁 二.事务1.为了保证数据的一致性和完整性,让数据库的多项操作合并为一个整体 ...

  3. Pycharm 自定义快捷键

    之前使用 Eclipse 时,快捷键 Ctrl + M 会使当前窗口最大化.这里配置 PyCharm 具有相同功能. 1)打开 File  >  Settings  >  Keymap 2 ...

  4. Python这么强大, 怎样才能快速入坑?

    作为一种年轻的编程语言,Python为何能在短短几年的时间内就以迅雷不及掩耳之势驰骋编程界?答案很简单,在人工智能时代,AlphaGo 都在使用的 Python语言,是最接近 AI 的编程语言. 随着 ...

  5. Redis学习之SDS源码分析

    一.SDS的简单介绍 SDS:简单动态字符串(simple dynamic string) 1)SDS是Redis默认的字符表示,比如包含字符串值的键值对都是在底层由SDS实现的 2)SDS用来保存数 ...

  6. 对写博客的n种思考

    喜欢才能坚持 开始写博客的原因非常功利,功利到不好意思说. 反正你们也懂的,就那么几种. 问题是,如果心态一直这么功利,而写博客的前期回报几乎为零,情绪会变得沮丧,不知如何继续. 不过后来想想,其实做 ...

  7. 原生jS之-去掉字符串开头和结尾的空字符

    怎么解决这个问题?? 思路就是我们利用正则匹配到所谓的空格,然后替换为空字符,我们要用到的是str的replace API 代码如下: <!DOCTYPE html> <html l ...

  8. springboot在yml中配置控制台sql打印方法小结

    方法一: logging: level: debug level.io.renren: debug path: logs/ file: admin.log   方法二 logging:    leve ...

  9. 一些iptables配置

    第一条是封堵22,80,8080端口的输出,第二条是为该ip的80端口设置输出白名单,亲测有效:第三条是禁止所有UDP报文的输出 iptables -I OUTPUT -p tcp -m multip ...

  10. 现代程序设计 homework-06

    写代码爽还是读代码爽? 当然是写代码爽好吧... 读代码明显是读+写两倍的工作量好么... 本次作业要求: 1) 把程序编译通过, 跑起来. 读懂程序,在你觉得比较难懂的地方加上一些注释,这样大家就能 ...