Linux内核调试技术之Kprobes
使用Kprobes(转)
![使用Kprobes(转)](https://img.taocdn.com/s3/m/7097c3bb960590c69ec376c5.png)
使用Kprobes调试内核将printk插入到运行中的Linux 内核Prasanna S. Panchamukhi, 开发人员,Linux Technology Center, IBM India Software Labs 简介:使用printk收集Linux ™ 内核的调试信息是一个众所周知的方法——而使用了Kprobes,不需要经常重新引导和重新编译内核就可以完成这一任务。
Kprobes与2.6 内核结合起来提供了一个动态插入printk's的轻量级、无干扰而且强大的装置。
记录调试信息(比如内核栈追踪、内核数据结构和寄存器)日志从来没有这么简单过!本文的标签:tools标记本文!发布日期: 2004 年9 月19 日级别:初级访问情况: 5004 次浏览评论: 0 (查看 | 添加评论 - 登录)平均分(7个评分)为本文评分Kprobes是Linux 中的一个简单的轻量级装置,让您可以将断点插入到正在运行的内核之中。
Kprobes提供了一个强行进入任何内核例程并从中断处理器无干扰地收集信息的接口。
使用Kprobes可以轻松地收集处理器寄存器和全局数据结构等调试信息。
开发者甚至可以使用Kprobes来修改寄存器值和全局数据结构的值。
为完成这一任务,Kprobes向运行的内核中给定地址写入断点指令,插入一个探测器。
执行被探测的指令会导致断点错误。
Kprobes钩住(hook in)断点处理器并收集调试信息。
Kprobes甚至可以单步执行被探测的指令。
安装要安装Kprobes,需要从Kprobes主页下载最新的补丁(参阅参考资料中的链接)。
打包的文件名称类似于kprobes-2.6.8-rc1.tar.gz。
解开补丁并将其安装到Linux 内核:$tar -xvzf kprobes-2.6.8-rc1.tar.gz$cd /usr/src/linux-2.6.8-rc1$patch -p1 < ../kprobes-2.6.8-rc1-base.patchKprobes利用了SysRq键,这个DOS 时代的产物在Linux 中有了新的用武之地(参阅参考资料)。
ftrace hook函数
![ftrace hook函数](https://img.taocdn.com/s3/m/72905530cd1755270722192e453610661ed95af5.png)
ftrace hook函数一、概述ftrace是Linux内核中的一个跟踪框架,它提供了一种轻量级的方法来监控内核函数的调用。
在ftrace中,可以通过hook函数来实现对内核函数的跟踪。
本文将详细介绍如何编写ftrace hook函数,并提供一个全面的详细的函数。
二、编写ftrace hook函数1. 确定要跟踪的内核函数首先,需要确定要跟踪的内核函数。
可以通过查看内核源代码或使用工具(如SystemTap)来确定需要跟踪的函数。
2. 编写hook函数接下来,需要编写hook函数。
在Linux内核中,可以使用两种方式来编写hook函数:kprobes和uprobes。
kprobes是一种在内核代码中插入probe点(即断点)并执行用户定义回调函数的技术。
通过kprobes,可以实现对任意内核代码段进行跟踪。
uprobes是一种在用户空间程序中插入probe点并执行用户定义回调函数的技术。
通过uprobes,可以实现对用户空间程序中任意代码段进行跟踪。
本文将以kprobes为例进行讲解。
3. 注册hook函数注册hook函数时,需要指定要跟踪的内核函数和回调函数。
可以使用以下代码注册hook:```cstatic struct kprobe kp = {.symbol_name = "function_to_trace",.pre_handler = pre_handler,};int register_hook(void)int ret;ret = register_kprobe(&kp);if (ret < 0) {printk(KERN_ERR "Failed to register kprobe\n");return ret;}printk(KERN_INFO "Registered kprobe forfunction_to_trace\n");return 0;}```在上述代码中,kp是一个kprobe结构体,其中symbol_name字段指定要跟踪的内核函数名,pre_handler字段指定回调函数。
Linux内核调试和工具使用
![Linux内核调试和工具使用](https://img.taocdn.com/s3/m/a29fbf58011ca300a6c390db.png)
Linux内核调试和工具使用1.摘要Linux内核调试跟普通用户态c程序调试的工作有点不同,如果所添加或修改代码是以模块形式加载于内核,则除了编码过程中包含的头文件、各种锁、信号量不同外,跟用户态的c程序的调试工作也没什么差别;但如果所修改代码是必须直接加入内核,并且会随linux系统启动而启动,则为了更容易调试,免于因代码错误系统死机而无法获得bug环境,就得使用kgdb远程调试或通过串口信将打印信息打印到另一台机子上。
本文主要介绍在虚拟机上进行linux内核调试时一些常用工具的使用和可能经常会遇到的一些问题的解决方法。
编写此份文档的目的是为了不让一部分同事对linux内核编译从未知开始摸索(将花费大量时间),提高工作效率。
本文档知识量不高,主要是针对从未接触过linux内核编码的同事使用。
2.Linux内核中编码注意项事1.不同版本的内核源码,相同模块中的部分代码可能不同,如一些头文件或接口所在位置或参数可能不同,因此在编码前要确定在哪一个版本中编码,否者在不同版本进行代码移植时出现莫名其妙的bug是件令人头痛的事情。
Linux的内核源码放在/usr/src/ 或/usr/src/kernels中,查看当前系统所使用的内核的命令是:uname –r3.调试相关工具使用简介3.1.samba工具共享文件夹Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。
samba是一个工具套件,在Unix上实现SMB(Server Message Block)协议,或者称之为NETBIOS/LanManager协议.SMB协议通常是被windows 系列用来实现磁盘和打印机共享.1.安装samba工具时,首先要确保虚拟机与pc能够相互ping通,虚拟机有自己的的ip,同时虚拟机的连接模式是bridged,虚拟机不能上外网没关系。
Pc:虚拟机:2.如果是redhat的linxu系统,一般都装好了samba的图形界面软件,我用的是centos,是redhat其中一个版本,所以也有带。
Linux内核调试工具Kprobe机制的研究
![Linux内核调试工具Kprobe机制的研究](https://img.taocdn.com/s3/m/98d7864acf84b9d528ea7ad5.png)
Linux内核调试工具Kprobe机制的研究李清干* 邵作之(华北电力大学计算机科学与技术学院,北京 102206)摘 要:在传统内核调试过程中,我们经常使用print k作为内核调试的一种方法,但这种方法执行速度相对较慢,在对响应时间要求比较严格的内核控制路径(如中断)中不宜采用它。
Kprobe(K erne l probe)与2 6内核结合起来提供了一个动态插入pri n t k的轻量级、无干扰而且强大的装置,使用K probe不需要经常重新引导和重新编译内核就可以完成这一任务。
本文重点介绍K probe调试机制原理以及同内核接口。
关键词:L inux内核;K probe;探测点一、Kp robe机制简介K probe是IB M公司开发的一个轻量级调试工具,它允许内核运行时通过加载模块设置探测器,内核运行到探测点时便执行其相应的处理函数,这是以前的所有工具都做不到的。
K probe作为一个动态地收集调试和性能信息的工具,它从Dprobe项目派生而来,是一种非破坏性工具,用户用它几乎可以跟踪任何函数或被执行的指令以及一些异步事件(如ti m er)。
它的基本工作机制是:用户指定一个探测点,并把一个用户定义的处理函数关联到该探测点,当内核执行到该探测点时,相应的关联函数被执行,然后继续执行正常的代码路径。
使用K probe可以轻松地通过收集处理器寄存器和全局数据结构等调试信息。
开发者甚至可以使用K probe来修改寄存器值和全局数据结构的值。
K probe实现了三种类型的探测点:kprobes、j probes和kretprobes(也叫返回探测点)。
kprobes是可以被插入到内核的任何指令位置的探测点,j probes则只能被插入到一个内核函数的入口,而kre t probes则是在指定的内核函数返回时才被执行。
这三种类型可以用在不同情况的上下文中。
二、Kp robe机制实现原理当安装一个kprobes探测点时,K probe首先备份被探测的指令,然后使用断点指令(即在i386和x86_64的i nt3指令)来取代被探测指令的头一个或几个字节。
Linux内核调试技术——kprobe使用与实现
![Linux内核调试技术——kprobe使用与实现](https://img.taocdn.com/s3/m/c18003c849649b6648d74718.png)
Linux内核调试技术——kprobe使用与实现一、kprobes技术背景开发人员在内核或者模块的调试过程中,往往会需要要知道其中的一些函数有无被调用、何时被调用、执行是否正确以及函数的入参和返回值是什么等等。
比较简单的做法是在内核代码对应的函数中添加日志打印信息,但这种方式往往需要重新编译内核或模块,重新启动设备之类的,操作较为复杂甚至可能会破坏原有的代码执行过程。
而利用kprobes技术,用户可以定义自己的回调函数,然后在内核或者模块中几乎所有的函数中(有些函数是不可探测的,例如kprobes自身的相关实现函数,后文会有详细说明)动态的插入探测点,当内核执行流程执行到指定的探测函数时,会调用该回调函数,用户即可收集所需的信息了,同时内核最后还会回到原本的正常执行流程。
如果用户已经收集足够的信息,不再需要继续探测,则同样可以动态的移除探测点。
因此kprobes技术具有对内核执行流程影响小和操作方便的优点。
kprobes技术包括的3种探测手段分别时kprobe、jprobe和kretprobe。
首先kprobe是最基本的探测方式,是实现后两种的基础,它可以在任意的位置放置探测点(就连函数内部的某条指令处也可以),它提供了探测点的调用前、调用后和内存访问出错3种回调方式,分别是pre_handler、post_handler和fault_handler,其中pre_handler函数将在被探测指令被执行前回调,post_handler会在被探测指令执行完毕后回调(注意不是被探测函数),fault_handler会在内存访问出错时被调用;jprobe基于kprobe实现,它用于获取被探测函数的入参值;最后kretprobe从名字种就可以看出其用途了,它同样基于kprobe实现,用于获取被探测函数的返回值。
kprobes的技术原理并不仅仅包含存软件的实现方案,它也需要硬件架构提供支持。
其中涉及硬件架构相关的是CPU的异常处理和单步调试技术,前者用于让程序的执行流程陷入到用户注册的回调函数中去,而后者则用于单步执行被探测点指令,因此并不是所有的架构均支持,目前kprobes技术已经支持多种架构,包括i386、x86_64、ppc64、ia64、sparc64、arm、ppc和mips(有些架构实现可能并不完全,具体可参考内核的Documentation/kprobes.txt)。
Linux内核参数及Oracle相关参数调整
![Linux内核参数及Oracle相关参数调整](https://img.taocdn.com/s3/m/6886d50d6ad97f192279168884868762caaebbf7.png)
Linux内核参数及Oracle相关参数调整修改内核参数的⽅法RedHat向管理员提供了⾮常好的⽅法,使我们可以在系统运⾏时更改内核参数,⽽不需要重新引导系统。
这是通过/proc虚拟⽂件系统实现的。
/proc/sys⽬录下存放着⼤多数的内核参数,并且设计成可以在系统运⾏的同时进⾏更改。
更改⽅法有两种:⽅法⼀:修改/proc/sys⽬录下的相应⽂件,⽐如:/proc/sys/net/ipv4/ip_forward,修改后⽴刻可⽤,不⽤重启系统,但重启系统,会恢复到默认值。
⽅法⼆:修改/etc/sysctl.conf ⽂件,该⽂件中以(变量=值)的形式设置内核参数,修改后,不能⽴刻⽣效,需要执⾏/sbin/sysctl –p 命令,使配置⽂件⽣效。
注意: /etc/sysctl.conf和/proc/sys下的⽂件其实都对应着⼀个参数,它们之间的对应关系,有简单规则:将/proc/sys中的⽂件转换成sysctl中的变量的规则:1.去掉前⾯部分/proc/sys2.将⽂件名中的斜杠变为点这两条规则可以将/proc/sys中的任⼀⽂件名转换成sysctl中的变量名。
例如:/proc/sys/net/ipv4/ip_forward =》 net.ipv4.ip_forward/proc/sys/kernel/hostname =》 kernel.hostname可以使⽤下⾯命令查询所有可修改的变量名例⼦:以打开内核的转发功能。
IP转发是指允许系统对来源和⽬的地都不是本机的数据包通过⽹络,RedHat默认屏蔽此功能,在需要⽤本机作为路由器、NAT等情况下需要开启此功能。
⽅法⼀:修改/proc下内核参数⽂件内容直接修改内核参数ip_forward对应在/proc下的⽂件/proc/sys/net/ipv4/ip_forward。
⽤下⾯命令查看ip_forward⽂件内容:# cat /proc/sys/net/ipv4/ip_forward该⽂件默认值0是禁⽌ip转发,修改为1即开启ip转发功能。
Linux内核调试机制源代码分析
![Linux内核调试机制源代码分析](https://img.taocdn.com/s3/m/2d82c14bf7ec4afe04a1df4b.png)
kimage_entry_t *entry; kimage_entry_t *last_entry; unsigned long destination; unsigned long start; struct page *control_code_page; struct page *swap_page; unsigned long nr_segments; struct kexec_segment segment[KEXEC_SEGMENT_MAX]; /*段数组*/ struct list_head control_pages; struct list_head dest_pages; struct list_head unuseable_pages; /* 分配给崩溃内核的下一个控制页的地址*/ unsigned long control_page; /* 指定特殊处理的标识*/ unsigned int type : 1; #define KEXEC_TYPE_DEFAULT 0 #define KEXEC_TYPE_CRASH 1 unsigned int preserve_context : 1; };
内核 kexec 接口函数说明如下:
extern void machine_kexec(struct kimage *image); /*启动内核映像*/ extern int machine_kexec_prepare(struct kimage *image); /*建立内核映 像所需要的控制页*/ extern void machine_kexec_cleanup(struct kimage *image); extern asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment __user *segments, unsigned long flags); /*装 载内核的系统调用*/ extern int kernel_kexec(void); /*启动内核*/
kprobe
![kprobe](https://img.taocdn.com/s3/m/4e5728136bd97f192279e962.png)
通过kprobe跟踪do_execve函数的执行环境 (2012-07-12 14:56)标签: 转载原文地址:通过kprobe跟踪do_execve函数的执行环境作者:MagicBoy2010kprobe可以动态跟踪某一内核函数的执行情况而无需修改内核,当然为了达到这样目的,我们需要自己写一个小的内核模块,不过这也要比修改内核源码要来得方便的多,我觉得这种方法可以形象地称之为“无损探测”。
下面是利用<<DEBUG HACKS>>中的一小段代码,经过适当改写完善,来探测一个U盘加入系统时,do_execve所执行的环境参数。
kprobe的原理大约是在执行被探测函数前先行获得控制权,执行内核模块所注册的回调函数,之后再把控制权转给被探测的函数,这个原理很有意思,有进一步分析的必要。
以下是内核模块代码:1.#include <linux/module.h>2.#include <linux/kprobes.h>3.#include <linux/kallsyms.h>4.5.struct kprobe kp;6.7.int handler_pre(struct kprobe *p, struct pt_regs *regs)8.{9.printk(KERN_INFO "|pid: %6d |comm: %10s |filename = %10s|\n",10.current->pid, current->comm,(char *)regs->di);11.return 0;12.}13.14.static __init int init_kprobe_sample(void)15.{16.kp.symbol_name ="do_execve";17.kp.pre_handler = handler_pre;18.register_kprobe(&kp);19.printk(KERN_INFO "---------------kprobe forexecve--------------\n");20.return 0;21.}22.23.static __exit void cleanup_kprobe_sample(void)24.{25.unregister_kprobe(&kp);26.}27.28.module_init(init_kprobe_sample);29.module_exit(cleanup_kprobe_sample);30.31.MODULE_LICENSE("GPL");insmod这个模块之后,探测活动就正式开始了,下面是往系统插入一个U盘时,kprobe回调函数的输出:1.root@build-server:/home/dennis/debug/kprobe# dmesg -c2.[10370.912471]usb 1-1.3:new high-speed USB device number 9 usingehci_hcd3.[10370.988796]|pid: 3296 |comm: kworker/u:3 |filename =/sbin/myhotplug|4.[10370.989038]|pid: 3297 |comm: kworker/u:3 |filename =/sbin/myhotplug|5.[10370.989146]|pid: 3298 |comm: udevd |filename =/lib/udev/mtp-probe|6.[10370.989192]|pid:3299 |comm:myhotplug |filename =/bin/touch|7.[10370.989496]|pid:3300 |comm:myhotplug |filename =/bin/touch|8.[10370.989730] scsi11 : usb-storage 1-1.3:1.09.[10370.989768]|pid: 3303 |comm: kworker/u:3 |filename =/sbin/myhotplug|10.[10370.989861]|pid: 3304 |comm: kworker/u:3 |filename =/sbin/myhotplug|11.[10370.990137]|pid:3305 |comm:myhotplug |filename =/bin/touch|12.[10370.990212]|pid:3306 |comm:myhotplug |filename =/bin/touch|13.[10371.249360]|pid: 3307 |comm: udevd |filename =/lib/udev/usb_id|14.[10371.992667] scsi 11:0:0:0: Direct-Access TOSHIBA TransMemory1.00 PQ: 0 ANSI: 215.[10371.992972]|pid: 3309 |comm: kworker/u:3 |filename =/sbin/myhotplug|16.[10371.993341]|pid:3310 |comm:myhotplug |filename =/bin/touch|17.[10371.993360]|pid: 3311 |comm: kworker/u:3 |filename =/sbin/myhotplug|18.[10371.993636]|pid:3312 |comm:udevd |filename =/sbin/modprobe|19.[10371.993712]|pid:3313 |comm:myhotplug |filename =/bin/touch|20.[10371.993777]|pid: 3314 |comm: kworker/u:3 |filename =/sbin/myhotplug|21.[10371.994364]|pid: 3316 |comm: kworker/u:2 |filename =/sbin/myhotplug|22.[10371.994563]|pid:3317 |comm:myhotplug |filename =/bin/touch|23.[10371.994797]|pid: 3318 |comm: kworker/u:2 |filename =/sbin/myhotplug|24.[10371.994830] sd 11:0:0:0: Attached scsi generic sg3 type 025.[10371.994886]|pid: 3319 |comm: kworker/u:2 |filename =/sbin/myhotplug|26.[10371.995249]|pid:3320 |comm:myhotplug |filename =/bin/touch|27.[10371.995506]|pid:3321 |comm:myhotplug |filename =/bin/touch|28.[10371.995538]|pid:3322 |comm:myhotplug |filename =/bin/touch|29.[10371.995786]sd 11:0:0:0:[sdc]15654848 512-byte logical blocks:(8.01 GB/7.46 GiB)30.[10371.996281] sd 11:0:0:0:[sdc] Write Protect is off31.[10371.996282] sd 11:0:0:0:[sdc] Mode Sense: 65 44 09 3032.[10371.996788] sd 11:0:0:0:[sdc] No Caching mode page present33.[10371.996862] sd 11:0:0:0:[sdc] Assuming drive cache: writethrough34.[10371.996996]|pid: 3323 |comm: kworker/u:2 |filename =/sbin/myhotplug|35.[10371.997387]|pid:3324 |comm:myhotplug |filename =/bin/touch|36.[10371.999537] sd 11:0:0:0:[sdc] No Caching mode page present37.[10371.999609] sd 11:0:0:0:[sdc] Assuming drive cache: writethrough38.[10372.000283] sdc: sdc139.[10372.000358]|pid: 3325 |comm: kworker/u:2 |filename =/sbin/myhotplug|40.[10372.000458]|pid: 3326 |comm: kworker/u:2 |filename =/sbin/myhotplug|41.[10372.000711]|pid:3327 |comm:myhotplug |filename =/bin/touch|42.[10372.000820]|pid:3328 |comm:myhotplug |filename =/bin/touch|43.[10372.000865]|pid: 3329 |comm: udevd |filename =/lib/udev/usb_id|44.[10372.001676]|pid: 3330 |comm: udevd |filename =/lib/udev/path_id|45.[10372.002411] sd 11:0:0:0:[sdc] No Caching mode page present46.[10372.002459]|pid: 3331 |comm: udevd |filename =/sbin/blkid|47.[10372.002484] sd 11:0:0:0:[sdc] Assuming drive cache: writethrough48.[10372.002564] sd 11:0:0:0:[sdc] Attached SCSI removable disk49.[10372.066849]|pid: 3332 |comm: udevd |filename =/lib/udev/udisks-part-id|50.[10372.070023]|pid: 3333 |comm: udevd |filename =/lib/udev/hdparm|51.[10372.070633]|pid: 3334 |comm: hdparm |filename =/bin/grep|52.[10372.071212]|pid: 3335 |comm: hdparm |filename =/bin/egrep|53.[10372.071930]|pid: 3337 |comm: hdparm |filename =/bin/egrep|54.[10372.073162]|pid: 3339 |comm: udevd |filename =/sbin/blkid|55.[10372.127677]|pid: 3341 |comm: udevd |filename =/lib/udev/udisks-part-id|56.[10373.752620]|pid: 3342 |comm: bash |filename =/bin/dmesg|如果仔细分析上面的输出,会发现不少有趣的信息,比如udevd与mtp-probe,hdparm等等。
Linux内核调试技术——jprobe使用与实现
![Linux内核调试技术——jprobe使用与实现](https://img.taocdn.com/s3/m/bea4bd3f915f804d2b16c17b.png)
Linux内核调试技术——jprobe使用与实现1、jprobe使用实例使用jprobe探测函数的入参值,需要编写内核模块。
同kprobe一样,内核同样提供了jprobe 的实例程序jprobe_example.c(位于sample/kprobes目录),该程序实现了探测do_fork函数入参的功能,用户可以以它为模板来探测其他函数(当然不是说什么函数都能探测的,限制同kprobe一样,另外需要注意的是一个被探测函数只能注册一个jprobe)。
在分析jprobe_example.c之前先熟悉一下jprobe的基本结构与API接口。
1.1、jprobe结构体与API介绍struct jprobe结构体定义如下:[cpp] view plain copy 在CODE上查看代码片派生到我的代码片/** Special probe type that uses setjmp-longjmp type tricks to resume* execution at a specified entry with a matching prototype corresponding* to the probed function - a trick to enable arguments to become* accessible seamlessly by probe handling logic.* Note:* Because of the way compilers allocate stack space for local variables* etc upfront, regardless of sub-scopes within a function, this mirroring* principle currently works only for probes placed on function entry points.*/struct jprobe {struct kprobe kp;void *entry; /* probe handling code to jump to */};该结构非常的简单,仅包含了一个kprobe结构(因为它是基于kprobe实现的)和一个entry 指针,它保存的是探测点执行回调函数的地址,当触发调用被探测函数时,保存到该指针的地址会作为目标地址跳转执行(probe handling code to jump to),因此用户指定的探测函数得以执行。
Linux 系统内核的调试.
![Linux 系统内核的调试.](https://img.taocdn.com/s3/m/fb81f80b3c1ec5da50e270ed.png)
Linux 系统内核的调试调试是软件开发过程中一个必不可少的环节,在 Linux 内核开发的过程中也不可避免地会面对如何调试内核的问题。
但是,Linux 系统的开发者出于保证内核代码正确性的考虑,不愿意在 Linux 内核源代码树中加入一个调试器。
他们认为内核中的调试器会误导开发者,从而引入不良的修正[1].所以对 Linux 内核进行调试一直是个令内核程序员感到棘手的问题,调试工作的艰苦性是内核级的开发区别于用户级开发的一个显著特点。
尽管缺乏一种内置的调试内核的有效方法,但是 Linux 系统在内核发展的过程中也逐渐形成了一些监视内核代码和错误跟踪的技术。
同时,许多的补丁程序应运而生,它们为标准内核附加了内核调试的支持。
尽管这些补丁有些并不被 Linux 官方组织认可,但他们确实功能完善,十分强大。
调试内核问题时,利用这些工具与方法跟踪内核执行情况,并查看其内存和数据结构将是非常有用的。
本文将首先介绍 Linux 内核上的一些内核代码监视和错误跟踪技术,这些调试和跟踪方法因所要求的使用环境和使用方法而各有不同,然后重点介绍三种 Linux 内核的源代码级的调试方法。
1. Linux 系统内核级软件的调试技术printk() 是调试内核代码时最常用的一种技术。
在内核代码中的特定位置加入printk() 调试调用,可以直接把所关心的信息打打印到屏幕上,从而可以观察程序的执行路径和所关心的变量、指针等信息。
Linux 内核调试器(Linux kernel debugger,kdb)是 Linux 内核的补丁,它提供了一种在系统能运行时对内核内存和数据结构进行检查的办法。
Oops、KDB在文章掌握 Linux 调试技术有详细介绍,大家可以参考。
Kprobes 提供了一个强行进入任何内核例程,并从中断处理器无干扰地收集信息的接口。
使用 Kprobes 可以轻松地收集处理器寄存器和全局数据结构等调试信息,而无需对Linux内核频繁编译和启动,具体使用方法,请参考使用 Kprobes 调试内核。
linux内核配置make menuconfig菜单详解
![linux内核配置make menuconfig菜单详解](https://img.taocdn.com/s3/m/56679a4fa8956bec0975e3a9.png)
LINUX内核配置MAKE MENUCONFIG菜单详解我们在linux内核裁剪过程中,进入内核所在目录,键入 make menuconfig 就会看到一堆的配置菜单,它们具体代表什么含义呢?我们该如何取舍呢?这里把近期收集到的一些信息做一个总结。
1、General setup代码成熟度选项,它又有子项:1.1、prompt for development and/or incomplete code/drivers该选项是对那些还在测试阶段的代码,驱动模块等的支持。
一般应该选这个选项,除非你只是想使用 LINUX 中已经完全稳定的东西。
但这样有时对系统性能影响挺大。
1.2、Cross-compiler tool prefix交叉编译工具前缀,例如:Cross-compiler tool prefix值为: (arm-linux-)1.3、Local version - append to kernel release内核显示的版本信息,填入 64字符以内的字符串,你在这里填上的字符口串可以用uname -a 命令看到。
1.4、Automatically append version information to the version string自动在版本字符串后面添加版本信息,编译时需要有perl以及git仓库支持1.5、Kernel compression mode (Gzip) --->有四个选项,这个选项是说内核镜像要用的压缩模式,回车一下,可以看到gzip,bzip2,lzma,lxo,一般可以按默认的gzip,如果要用bzip2,lzma,lxo要先装上支持1.6、Support for paging of anonymous memory (swap)使用交换分区或交换文件来做为虚拟内存,一定要选上。
1.7、System V IPC表示系统的进程间通信Inter Process Communication,它用于处理器在程序之间同步和交换信息,如果不选这项,很多程序运行不起来,必选。
Linux内核调试
![Linux内核调试](https://img.taocdn.com/s3/m/eae8610abb68a98271fefa10.png)
可以看到,jiffies 的值得到了更新。
1.7.2 调试模块
由于模块并没有作为 vmlinux 的一部分传给 gdb,因此必须通过某种方法把模块信息告 知 gdb。 1.模块文件的组成
Linux 的模块是 ELF 格式的可执行映像,分成了很多个 section。与调试关系较为密切的
的三个 section 如下: .text:包含了模块的可执行代码。 .bss 和.data:包括了模块的变量(在模块编译阶段被初始化的变量在.data,其他的 在.bss )
(1)启动 gdb。
在第一行调用 gdb 时所传入的参数中: vmlinux:未压缩的 ELF 内核可执行文件变量。 此时可以通过 p 命令查看系统变量,例如
在没有选中 CONFIG_DEBUG_IN FO 时也可查看 jiffies
需要注意的是,从上图中可以看出,虽然 jiffies 是不停变换的,但是 gdb 每次读取同一 个变量时将得到相同的值,这是因为 gdb 对读到的值进行了缓存。如果希望去掉缓存的影响, 可以使用 core-file 命令。
(1)如果不清楚当前正在运行的内核源代码的目录,可以通过如下方法查看。
(2)进入内核源代码所在目录,通过 make menuconfig 命令进入编译选项配置环境, 如图 1.1 所示。
调试内核
图 1.1 编译选项配置环境
在选项配置环境中每个选项有“*”(编译进内核)、“M”(以模块方式编译)和“”(不 编译)三种状态,可以分别使用“Y”、“M”和“N”键来设置。 2.配置编译选项
(2)加载模块信息。模块名称和.text 基址是 add-symbol-file 命令的必要参数,.bss 和.data 的基址可使用-s 选项传给 add-symbol-file 命令。
Linux内核调试方法总结
![Linux内核调试方法总结](https://img.taocdn.com/s3/m/dd7a99355627a5e9856a561252d380eb62942310.png)
二 内核中的bug
内核中的bug也是多种多样的。它们的产生有无数的原因,同时表象也变化多端。从隐藏在源代码中的错误到展现在目击者面前的bug,其发作往往是一系列连锁反应的事件才可能出发的。虽然内核调试有一定的困 难,但是通过你的努力和理解,说不定你会喜欢上这样的挑战。
三 内核调试配置选项
学习编写驱动程序要构建安装自己的内核(标准主线内核)。最重要的原因之一是:内核开发者已经建立了多项用于调试的功能。但是由于这些功能会造成额外的输出,并导致能下降,因此发行版厂商通常会禁止 发行版内核中的调试功能。
5 } while (0)
6 #endif
7
8 #ifndef HAVE_ARCH_BUG_ON
9
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
10 #endif
当调用这两个宏的时候,它们会引发OOPS,导致栈的回溯和错误消息的打印。 ※ 可以把这两个调用当作断言使用,如:BUG_ON(bad_thing);
6 [*] Spinlock debugging: sleep-inside-spinlock checking
7
[*] Compile the kernel with debug info
8 Device Drivers --->
9
Generic Driver Options --->
10
[*] Driver Core verbose debug messages
6 dmesg dmesg 命令也可用于打印和控制内核环缓冲区。这个命令使用 klogctl 系统调用来读取内核环缓冲区,并将它转发到标准输出(stdout)。这个命令也可以用来清除内核环缓冲区(使用 -c 选项),设置控制台日志 级别(-n 选项),以及定义用于读取内核日志消息的缓冲区大小(-s 选项)。注意,如果没有指定缓冲区大小,那么 dmesg 会使用 klogctl 的SYSLOG_ACTION_SIZE_BUFFER 操作确定缓冲区大小。
linux内核开发面试题
![linux内核开发面试题](https://img.taocdn.com/s3/m/9e2fd57f86c24028915f804d2b160b4e767f81a1.png)
linux内核开发面试题一、简介Linux内核是开源操作系统Linux的核心组成部分,负责管理计算机的硬件资源并提供各种系统服务。
Linux内核开发面试题是在面试过程中常见的一种考察方式,用于评估面试者对Linux内核的理解与掌握程度。
二、常见面试题1. 请简述Linux内核的架构及其组成部分。
2. 什么是进程和线程?它们在Linux内核中的实现方式是什么?3. 请解释虚拟内存的概念,并描述它在Linux内核中的实现原理。
4. Linux内核采用的调度算法有哪些?请分别介绍它们的特点。
5. 请描述Linux内核中的文件系统及其实现原理。
6. 什么是系统调用?请举例说明Linux内核中常用的系统调用接口。
7. 请解释Linux内核中的中断处理机制,并描述硬中断和软中断的区别。
8. 请简述Linux内核的设备驱动模型,并介绍驱动程序的开发流程。
9. 请阐述Linux内核的网络子系统及其组件,包括网络协议栈、套接字和网络设备驱动等。
10. 在进行Linux内核开发时,经常使用的调试技术有哪些?请简要说明它们的作用。
三、回答示范1. Linux内核的架构及组成部分Linux内核的架构主要由五个模块组成,分别是进程管理、内存管理、文件系统、设备驱动和网络子系统。
其中,进程管理模块负责创建、调度和销毁进程,内存管理模块负责管理系统的内存资源,文件系统模块提供了对文件和目录的操作接口,设备驱动模块负责管理硬件设备的访问,网络子系统模块提供了网络通信功能。
2. 进程和线程及其实现方式进程是计算机中正在运行的程序的实例,拥有独立的内存空间和执行上下文。
线程是进程内的一个执行单元,共享进程的资源。
在Linux 内核中,进程通过task_struct结构来表示,线程则通过clone系统调用来创建。
3. 虚拟内存的概念及实现原理虚拟内存是一种对物理内存的抽象和扩展,它为每个进程提供了独立的地址空间。
Linux内核通过页表将虚拟地址映射到物理地址,并采用页面置换算法(如LRU)来管理内存的使用。
kprobe原理
![kprobe原理](https://img.taocdn.com/s3/m/828a254b1fd9ad51f01dc281e53a580216fc50b8.png)
kprobe原理
kprobe是Linux内核提供的一项实时监控和诊断功能,它允许用户安装一个内核函数上的“kprobe”,以便对系统调用和内核函数执行时收集和报告实时数据。
kprobe的核心概念是类似断点调试中的探针,它是一种可共享的“hook”,可以在内核函数执行时插入到特定点上,使得程序可以在该点中断服务并以某种方式被调用。
整个流程可以分为三个步骤:首先,将kprobe插入到内核函数中,该探针将继续执行函数体内的代码;其次,根据需要收集参数和状态数据;最后,生成数据块,用于实时报告想要检测的数据。
kprobe可以解决操作系统中出现的性能问题,可以实时监测和分析内核函数的执行时间,以及不同系统调用之间的关系,可以加快系统诊断的效率,帮助开发者更好地了解系统运行状态,从而明确系统存在什么样的问题,进而可以提出有效的解决方案。
ftrace kprobe 例子 -回复
![ftrace kprobe 例子 -回复](https://img.taocdn.com/s3/m/33ce780132687e21af45b307e87101f69e31fb99.png)
ftrace kprobe 例子-回复[ftrace kprobe 例子]:如何使用ftrace kprobe技术进行性能分析?引言:随着软件系统规模的日益扩大和复杂性的增加,性能分析对于软件开发和系统优化变得越来越重要。
而ftrace kprobe技术作为Linux内核提供的一种性能分析工具,能够帮助开发者追踪和调试内核代码。
本文将介绍ftrace kprobe的基本概念和原理,并用一个例子来展示如何使用ftrace kprobe进行性能分析。
第一部分:ftrace kprobe的基本概念和原理1.1 什么是ftrace kprobe?ftrace是Linux内核提供的一种轻量级的性能分析工具,用于追踪内核代码的执行情况。
而kprobe是ftrace的一种扩展,它允许在内核函数的入口或出口处插入用户定义的probe点,以便在相应的位置添加自定义的跟踪代码。
1.2 ftrace kprobe的工作原理ftrace通过在内核代码中插入nop指令来实现跟踪功能,而kprobe 则利用x86架构的debug寄存器来监听内核函数的调用和返回。
当一个kprobe probe点被命中时,会触发一个中断,从而执行预先定义的probe 处理函数。
通过在probe处理函数中添加自定义的跟踪代码,可以获得所需的性能分析数据。
1.3 ftrace kprobe的应用场景ftrace kprobe可以用于各种性能分析场景,比如函数调用次数统计、函数执行时间测量、内存分配和释放跟踪等。
它可以帮助开发者快速定位性能瓶颈,优化系统性能。
第二部分:一个ftrace kprobe的使用示例2.1 环境准备在开始实际的ftrace kprobe示例之前,我们需要确保系统上已启用ftrace支持,并具备相应的调试权限。
这通常需要在内核编译配置中开启CONFIG_HAVE_KPROBES选项。
2.2 设置probe点假设我们要分析Linux内核中的函数do_fork(),以统计其被调用的次数。
Linux系统下Kprobes内核调试过程管理的研究与实现的开题报告
![Linux系统下Kprobes内核调试过程管理的研究与实现的开题报告](https://img.taocdn.com/s3/m/43ba49da0875f46527d3240c844769eae009a337.png)
Linux系统下Kprobes内核调试过程管理的研究与实现的开题报告一、选题的背景和意义Linux作为操作系统已经成为了大多数计算机领域的标配,尤其是在服务器端和嵌入式设备领域。
而对于一款操作系统来说,内核是最重要的部分,它直接关系到系统的稳定性和性能。
因此,在Linux系统中进行内核调试是非常必要的,而Kprobes技术在其中起到了重要的作用。
Kprobes是Linux系统提供的一种内核调试技术,它可以在任意函数入口或出口处添加断点,当断点触发时,可以执行指定的调试操作。
Kprobes技术可用于解决调试内核代码时遇到的问题,包括函数参数的跟踪、调用栈的跟踪、代码性能的分析等。
因此,在深入理解Kprobes技术的基础上,实现内核调试的目的是非常重要的。
二、选题的研究内容本文选题旨在探究Kprobes技术在Linux系统下的内核调试过程管理,具体包括以下方面的内容:1. Kprobes技术的原理与实现方式:介绍Kprobes技术的基本原理和实现方法,包括注册Kprobes、插入断点、执行指定的调试操作等。
2. Kprobes内核调试的过程管理:探究如何管理Kprobes内核调试过程,在调试过程中如何处理异常情况和遇到的错误,确保调试过程的安全和可靠性。
3. 实现Kprobes内核调试:基于以上两个方面的探究,实现一个Kprobes内核调试工具,包括注册Kprobes、插入断点、执行调试操作、控制调试过程等。
三、选题的研究目的本文选题的研究目的如下:1. 提高对Kprobes技术的理解:通过对Kprobes技术的探究,深入理解其原理与实现方式,从而更好地应用于内核调试。
2. 探究Kprobes内核调试过程管理方法:探究如何有效地进行Kprobes内核调试过程管理,在调试过程中遇到异常情况和错误如何处理。
3. 实现Kprobes内核调试工具:基于以上两个方面的探究,实现一个简单易用的Kprobes内核调试工具,简化内核调试的过程,提高调试效率。
kprobes架构原理
![kprobes架构原理](https://img.taocdn.com/s3/m/94879e0b0a4c2e3f5727a5e9856a561252d32184.png)
kprobes架构原理
Kprobes是一个用于动态内核调试和跟踪的Linux内核子系统。
它基于Linux内核的功能kprobe,并通过添加一层轻量级的钩
子来实现。
Kprobes架构的原理如下:
1. 创建Kprobe钩子:首先,用户可以使用特定的接口(如debugfs文件系统)来创建Kprobe钩子。
用户需要指定将要监
视的内核函数(或指定的地址)以及将在该函数执行前或执行后插入的预处理和后处理函数。
2. Hook到内核函数:Kprobes使用内核的kprobe子系统将钩
子插入到指定的内核函数中。
当指定的内核函数被执行时,钩子中的预处理函数会被调用。
3. 预处理函数:在钩子函数被调用之前,预处理函数会被执行。
预处理函数通常用于收集相关的调试信息或修改函数的参数。
4. Kprobe处理:Kprobe子系统完成预处理函数后,将执行原
始的函数代码。
5. 后处理函数:在被监视的内核函数执行完成后,后处理函数会被调用。
后处理函数通常用于收集执行过程中的状态信息或处理其他特定操作。
总的来说,Kprobes架构通过动态插入钩子到指定的内核函数
中,来执行预处理和后处理函数。
这允许开发者在内核函数执行前后收集信息、修改参数或采取其他操作,并在调试和跟踪过程中帮助定位问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
郭海林
2012.11.17
Kprobe 简介
• kprobe是一个动态地收集调试和性能信息的工具 • 从Dprobe项目派生而来,是一种非破坏性工具 • Linux下的Systemtap依赖的基础是kprobe • 实现了三种类型的探测点: kprobes, jprobes和kretprobes
来实现探测处理的
• 当kprobe注册的notifier被执行时
– 首先,执行关联到探测点的pre_handler函数
• 把相应的kprobe struct和保存的寄存器作为该函数的参数
– 其次,kprobe单步执行被探测指令的备份 – 最后,kprobe执行post_handler
• 等所有这些运行完毕后,紧跟在被探测指令后的指令流将被正常执行
• Gaining insight into the Linux® kernel with Kprobes
– /magazine/005mar05/features/kprobes/
• kprobes tutorial
– /~boutcher/kprobes/
• An introduction to KProbes
– /Articles/132196/
• 《Debug Hacks中文版—深入调试的技术和工具》 • Linux内核中Kprobes调试技术的实现
– /2008/11/821.html
– grep do_fork /boot/System.map-xxx
• 使用 nm 命令
– nm /boot/vmlinuz-xxx | grep do_fork
• 从 /proc/kallsyms 文件获得地址
– cat /proc/kallsyms | grep do_fork
• 使用 kallsyms_lookup_name() 函数
• Linux kernel documentation, Documentation/kprobes.txt
Thank You for Listening!
Understanding the Linux Kernel Read the fucking source code!
– 探测内核函数、全局变量 – 探测函数的参数
kprobes 应用实例(3)
• 利用kprobes 探测内核内部任意位置的信息(见kprobe_anyaddr.c)
– 如何获得任意位置的地址
• 找到与函数的开始位置的偏移
参考资料
• Kernel debugging with Kprobes
– /developerworks/library/l-kprobes/index.html
• Linux下的一个全新的性能测量和调式诊断工具Systemtap,第1部分:kprobe
– https:///developerworks/cn/linux/l-cn-systemtap1/
• 通过kprobe跟踪do_execve函数的执行环境
– /forum.php?mod=viewthread&tid=586
• 错误处理函数
– int fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr);
• 探测点卸载
– void unregister_kprobe(struct kprobe *kp);
获得内核函数探测地址的方法
• 从 System.map 文件直接得到地址
– kprobes是可以被插入到内核的任何指令位置的探测点 – jprobes则只能被插入到一个内核函数的入口 – kretprobes则是在指定的内核函数返回时才被执行
下面介绍kprobes 的工作机制 / 实现 / 实例。
kprobes工作机制(1)
kprobes工作机制(2)
• 安装一个kprobes探测点时
– kallsyms_lookup_name("do_fork")
kprobes 应用实例(1)
• kprobes 示例程序(见kprobe_example.c)
– kprobes 探测程ห้องสมุดไป่ตู้框架 – kprobes 探测的原理
kprobes 应用实例(2)
• 利用kprobes 探测内核函数与变量(见kprobe_doexecve.c)
kprobes 实现——数据结构
kprobes 实现——接口函数
• 注册探测点
– int register_kprobe(struct kprobe *kp);
• 探测点处理函数
– int pre_handler(struct kprobe *p, struct pt_regs *regs); – void post_handler(struct kprobe *p, struct pt_regs *regs, unsigned long flags);
– kprobe首先备份被探测的指令 – 使用断点指令(int3指令)来取代被探测指令的头一个或几个字节
• CPU执行到探测点时
– 将因运行断点指令而执行trap操作
• 导致保存CPU的寄存器 • 调用相应的trap处理函数
– trap处理函数将调用相应的notifier_call_chain中注册的所有notifier函数 – kprobe正是通过向trap对应的notifier_call_chain注册关联到探测点的处理函数