调试 – 观察Linux内核中的变量(内存地址)更改,并在更改时打印堆栈跟踪?
|
我想以某种方式“监视” Linux内核中的变量(或内存地址)(确切地说是内核模块/驱动程序);并找出改变它的原因 – 基本上,当变量改变时打印出堆栈跟踪. 例如,在this answer年末列出的内核模块testjiffy-hr.c中,我想在每次runcount变量更改时打印出堆栈跟踪;希望堆栈跟踪然后会提到testjiffy_timer_function,这确实是改变该变量的函数. 现在,我知道我可以使用kgdb连接到在虚拟机中运行的调试Linux内核,甚至可以设置断点(所以希望也是观察点) – 但问题是我实际上想要调试ALSA驱动程序,特别是播放dma_area缓冲区(我得到了一些意想不到的数据) – 这对时间非常敏感;并且运行调试内核本身会弄乱时间(更不用说在虚拟机中运行它)了. 这里更大的问题是回放dma_area指针仅在回放操作期间(或者换句话说,在_start和_stop处理程序之间)存在 – 所以我必须在每个_start回调中记录dma_area地址,然后以某种方式“在播放操作期间安排“用于”观看“. 所以我希望有一种方法可以直接在驱动程序代码中执行此类操作 – 例如,在此_start回调中添加一些代码来记录dma_area指针,并将其用作启动“watch”的命令的参数改变;从相应的回调函数打印堆栈跟踪. (我知道这也会影响时间,但我希望它能够“轻松”,不会过多地影响“实时”驱动程序操作). 所以我的问题是:在Linux内核中进行调试的这种技术是否存在? 如果不是:是否可以设置硬件(或软件)中断,该中断会对特定内存地址的更改做出反应?然后,我可以设置这样的中断处理程序,可以打印出堆栈跟踪吗? (虽然,我认为整个上下文在IRQ处理程序运行时会发生变化,因此可能会出现堆栈跟踪错误)? 如果没有:是否还有其他技术,这将允许我打印进程的堆栈跟踪,该跟踪更改存储在内核中给定内存位置的值(希望在实时的非调试内核中)? 解决方法非常感谢 @CosminRatiu和 Eugene的回复;多亏了那些,我发现:> debugging – Linux kernel hardware break points – Stack Overflow …我可以用它来开发我在这里发布的示例,testhrarr.c内核模块/驱动程序和Makefile(下面).它表明硬件观察点跟踪可以通过两种方式实现:使用perf程序,它可以不变地探测驱动程序;或者通过向驱动程序添加一些硬件断点代码(在示例中,由HWDEBUG_STACK定义变量包含). 本质上,调试像int这样的标准原子变量类型(如runcount变量)的内容很简单,只要它们被定义为内核模块中的全局变量,因此它们最终全局显示为内核符号.因此,下面的代码将testhrarr_添加为变量的前缀(以避免命名冲突).但是,由于需要解除引用,调试数组的内容可能有点棘手 – 这就是本文演示的内容,调试testhrarr_arr数组的第一个字节.它完成于: $echo `cat /etc/lsb-release` DISTRIB_ID=Ubuntu DISTRIB_RELEASE=11.04 DISTRIB_CODENAME=natty DISTRIB_DESCRIPTION="Ubuntu 11.04" $uname -a Linux mypc 2.6.38-16-generic #67-Ubuntu SMP Thu Sep 6 18:00:43 UTC 2012 i686 i686 i386 GNU/Linux $cat /proc/cpuinfo | grep "model name" model name : Intel(R) Atom(TM) CPU N450 @ 1.66GHz model name : Intel(R) Atom(TM) CPU N450 @ 1.66GHz testhrarr模块基本上在模块初始化时为小数组分配内存,设置定时器函数,并公开/ proc / testhrarr_proc文件(使用较新的proc_create接口).然后,尝试从/ proc / testhrarr_proc文件(例如,使用cat)读取将触发计时器功能,该功能将修改testhrarr_arr数组值,并将消息转储到/ var / log / syslog.我们期望testhrarr_arr [0]在操作期间会改变三次;一次在testhrarr_startup中,两次在testhrarr_timer_function中(由于换行). 使用perf 使用make构建模块后,您可以使用以下命令加载它: sudo insmod ./testhrarr.ko 此时,/ var / log / syslog将包含: kernel: [40277.199913] Init testhrarr: 0 ; HZ: 250 ; 1/HZ (ms): 4 ; hrres: 0.000000001 kernel: [40277.199930] Addresses: _runcount 0xf84be22c ; _arr 0xf84be2a0 ; _arr[0] 0xed182a80 (0xed182a80) ; _timer_function 0xf84bc1c3 ; my_hrtimer 0xf84be260; my_hrt.f 0xf84be27c kernel: [40277.220329] HW Breakpoint for testhrarr_arr write installed (0xf84be2a0) 注意,只是将testhrarr_arr作为硬件观察点的符号传递,扫描该变量的地址(0xf84be2a0),而不是数组的第一个元素的地址(0xed182a80)!因此,硬件断点不会触发 – 因此行为就好像硬件断点代码根本不存在(可以通过取消定义HWDEBUG_STACK来实现)! 因此,即使没有通过内核模块代码设置的硬件断点,我们仍然可以使用perf来观察内存地址的变化 – 在perf中,我们指定我们要监视的地址(这里是testhrarr_arr的第一个元素的地址,0xed182a80),以及应该运行的进程:这里我们运行bash,所以我们可以执行cat / proc / testhrarr_proc,它将触发内核模块定时器,然后是sleep 0.5,这将允许定时器完成. -a参数也是必需的,否则可能会遗漏一些事件: $sudo perf record -a --call-graph --event=mem:0xed182a80:w bash -c 'cat /proc/testhrarr_proc ; sleep 0.5' testhrarr proc: startup [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.485 MB perf.data (~21172 samples) ] 此时,/ var / log / syslog还包含以下内容: [40822.114964] testhrarr_timer_function: testhrarr_runcount 0 [40822.114980] testhrarr jiffies 10130528 ; ret: 1 ; ktnsec: 40822114975062 [40822.118956] testhrarr_timer_function: testhrarr_runcount 1 [40822.118977] testhrarr jiffies 10130529 ; ret: 1 ; ktnsec: 40822118973195 [40822.122940] testhrarr_timer_function: testhrarr_runcount 2 [40822.122956] testhrarr jiffies 10130530 ; ret: 1 ; ktnsec: 40822122951143 [40822.126962] testhrarr_timer_function: testhrarr_runcount 3 [40822.126978] testhrarr jiffies 10130531 ; ret: 1 ; ktnsec: 40822126973583 [40822.130941] testhrarr_timer_function: testhrarr_runcount 4 [40822.130961] testhrarr jiffies 10130532 ; ret: 1 ; ktnsec: 40822130955167 [40822.134940] testhrarr_timer_function: testhrarr_runcount 5 [40822.134962] testhrarr jiffies 10130533 ; ret: 1 ; ktnsec: 40822134958888 [40822.138936] testhrarr_timer_function: testhrarr_runcount 6 [40822.138958] testhrarr jiffies 10130534 ; ret: 1 ; ktnsec: 40822138955693 [40822.142940] testhrarr_timer_function: testhrarr_runcount 7 [40822.142962] testhrarr jiffies 10130535 ; ret: 1 ; ktnsec: 40822142959345 [40822.146936] testhrarr_timer_function: testhrarr_runcount 8 [40822.146957] testhrarr jiffies 10130536 ; ret: 1 ; ktnsec: 40822146954479 [40822.150949] testhrarr_timer_function: testhrarr_runcount 9 [40822.150970] testhrarr jiffies 10130537 ; ret: 1 ; ktnsec: 40822150963438 [40822.154974] testhrarr_timer_function: testhrarr_runcount 10 [40822.154988] testhrarr [ 5,7,9,11,13,] 要读取perf(一个名为perf.data的文件)的捕获,我们可以使用: $sudo perf report --call-graph flat --stdio
No kallsyms or vmlinux with build-id 5031df4d8668bcc45a7bdb4023909c6f8e2d3d34 was found
[testhrarr] with build id 5031df4d8668bcc45a7bdb4023909c6f8e2d3d34 not found,continuing without symbols
Failed to open /bin/cat,continuing without symbols
Failed to open /usr/lib/libpixman-1.so.0.20.2,continuing without symbols
Failed to open /usr/lib/xorg/modules/drivers/intel_drv.so,continuing without symbols
Failed to open /usr/bin/Xorg,continuing without symbols
# Events: 5 unknown
#
# Overhead Command Shared Object Symbol
# ........ ....... ............. ....................................
#
87.50% Xorg [testhrarr] [k] testhrarr_timer_function
87.50%
testhrarr_timer_function
__run_hrtimer
hrtimer_interrupt
smp_apic_timer_interrupt
apic_timer_interrupt
0x30185d
0x2ed701
0x2ed8cc
0x2edba0
0x9d0386
0x8126fc8
0x81217a1
0x811bdd3
0x8070aa7
0x806281c
__libc_start_main
0x8062411
6.25% cat [testhrarr] [k] testhrarr_timer_function
6.25%
testhrarr_timer_function
testhrarr_proc_show
seq_read
proc_reg_read
vfs_read
sys_read
syscall_call
0xaa2416
0x8049f4d
__libc_start_main
0x8049081
3.12% swapper [testhrarr] [k] testhrarr_timer_function
3.12%
testhrarr_timer_function
__run_hrtimer
hrtimer_interrupt
smp_apic_timer_interrupt
apic_timer_interrupt
cpuidle_idle_call
cpu_idle
start_secondary
3.12% cat [testhrarr] [k] 0x356
3.12%
0xf84bc356
0xf84bc3a7
seq_read
proc_reg_read
vfs_read
sys_read
syscall_call
0xaa2416
0x8049f4d
__libc_start_main
0x8049081
#
# (For a higher level overview,try: perf report --sort comm,dso)
#
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
