Linux内核常用的动态调试手段

栏目: IT技术 · 发布时间: 4年前

内容简介:本文介绍linux内核中几种常用的动态调试手段,也都是我常用的,都是在生产环境中直接使用,最常见的就是使用kprobe,kprobe具体的原理可以参考我以前写的这篇文章kprobe原理使用kprobe最常用的就是查询函数调用的参数和返回值:

本文介绍 linux 内核中几种常用的动态调试手段,也都是我常用的,都是在生产环境中直接使用, 不需要借助工具, 依照我的经验,去客户生产环境中解决问题,很多都不会预装perf、BPF工具,有的即使有perf这样的工具,也因为 工具 性能影响客户几千亿美金的正常业务,也会不让你使用。

最常见的就是使用kprobe,kprobe具体的原理可以参考我以前写的这篇文章kprobe原理

使用kprobe最常用的就是查询函数调用的参数和返回值:

cd /sys/kernel/debug/tracing

echo ‘p:myprobe do_sys_open fname_str=+0(%si):string' > kprobe_events

echo 'r:myretprobe do_sys_open $retval' >> kprobe_events

ls  ./events/kprobes/

enable  filter myprobe  myretprobe

使能kprobe event:

echo 1 >  ./events/kprobes/myprobe/enable

echo 1 >  ./events/kprobes/myretprobe/enable

cat  ./trace (可以看到系统中调用open的文件名和返回值)

Linux内核常用的动态调试手段

至于在kprobe_events文件中指定的寄存器(%si),基于具体平台的不同会不一样,可以预先使用perf工具查询到当前平台上获取函数参数的寄存器。

[root@u-jeff ~]# perf probe  'do_sys_open filename:string flags:u32'

Added new event:

...

[root@u-jeff ~]# cat /sys/kernel/debug/tracing/kprobe_events

p:probe/do_sys_open _text+2391184 filename_string=+0( %si ):string flags_u32= %dx :u32

第二类就是使用trace event:

比如像linux内核中最著名的函数__schedule()

static void __sched notrace __schedule(bool preempt)

{

...

trace_sched_switch(preempt, prev, next);

...

}

这种原理不用多说,是内核代码编译的时候就已经内嵌于函数中的,只需打开对应开关就可以看到固定格式的打印信息。

#pwd

/sys/kernel/debug/tracing/events/sched/sched_switch

#cat /sys/kernel/debug/tracing/trace

Linux内核常用的动态调试手段

系统中大量子系统中的函数都嵌入了这种trace event,只需针对性打开开关便可。

#pwd

/sys/kernel/debug/tracing/events

Linux内核常用的动态调试手段

还有一些函数里面没有内嵌trace event,或者有时想查看函数的调用堆栈,可以使用trace function + stack_trace

cd /sys/kernel/debug/tracing/

echo 0 > ./tracing_on

echo function > current_tracer

echo 1 > options/func_stack_trace

echo  "your function" > set_ftrace_filter

echo 1 > tracing_on

比如把 ”your function" 改成 schedule

cat ./trace   可以看到调用schedule时的函数堆栈,而不需要在函数中加上WARN_ON(1)这样的语句再重新编译内核。

Linux内核常用的动态调试手段

不管是function tracer还是 function_graph 这样的tracer,

cat ./available_tracers

hwlat blk function_graph wakeup_dl wakeup_rt wakeup function nop

我最佩服的就是实现此功能时同步代码段的方法,其实就是怎样从下面第一幅图变成第二幅图:

图一:

Linux内核常用的动态调试手段

图二:

Linux内核常用的动态调试手段

因为实现这些功能的原理就是在代码段函数头中插上预先设定好的函数调用,如果刚刚插入代码时,正好有程序跑到这块代码就好玩了,系统很可能会崩掉,在x86系统上采用的就是先在函数头中插入一个字节指令'cc',当其它进程执行此指令时,系统进入int3中断流程,

所以在do_int3中可以看到下面类似的代码:

Linux内核常用的动态调试手段

当插入‘cc'之后,把'cc'指令同步到所有的cpu,然后把’cc‘之后的代码换成函数调用代码,最后把’cc'换掉,一切都ok.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

交互设计

交互设计

. / 刘晓晖、张景 / 电子工业出版社 / 2003-6 / 39.00元

一起来看看 《交互设计》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具