内核有spinlock的调试选项,在spinlock被获取时会记录它的owner。
owner是一个struct task_struct指针,在owner里有pid字段,通过pid就能确认是哪个进程持有锁。
自己做了个实验,在同一个函数里两次调用spin_lock,直接锁死,然后用kdb结合gdb来找锁的持有者,可行。
(关于本文中kdb和gdb的使用方法见
http://blog.chinaunix.net/uid-26517122-id-4263265.html)
=======================================================================
(1) 确认内核中打开编译选项 CONFIG_DEBUG_SPINLOCK=y
(2) 挂死的时候进kdb
(3) bt看到spinlock调用栈,找到lock地址
0xc2481ebc 0xc1158e24 _raw_spin_lock+0xbd (
0xc241a2b0)
0xc2481ee0 0xc1246815 _spin_lock+0x22 (0xc241a2b0)
0xc2481efc 0xf8408156 [network]tcp_write_timer+0x7f (0xc241a280)
0xc2481f10 0xc1030bbf run_timer_softirq+0x1c1
0xc2481f60 0xc102b0ac __do_softirq+0xa7
0xc2481f8c 0xc102b173 do_softirq+0x26
0xc2481f98 0xc102b256 irq_exit+0x29
0xc2481fa0 0xc100e33a smp_apic_timer_interrupt+0x6f (invalid)
0xc2481fb0 0xc1003236 apic_timer_interrupt+0x2a (invalid, invalid, invalid)
在这里lock的地址是0xc241a2b0,也就是&lock的值,是函数的参数
(4) 根据偏移量得到lock指向的结构体中的owner字段的内存地址
gdb vmlinux......(gdb) p ((spinlock_t *)0)->owner
Cannot access memory at address
0xc
gdb p/x 0xc+0xc241a2b0
$1 =
0xc241a2bc
(5) 根据偏移量得到owner结构体中的pid字段的内存地址
gdb p ((struct task_struct *)0)->pid
Cannot access memory at address
0x204
gdb p/x 0x204+0xc241a2bc
$2 =
0xc241a4c0
(6) 在kdb中查看pid的值[0]
kdb> md 0xc241a4c0
00000325 00000325 f73c8000 f73c8000 %...%.....<...<.
所以pid是0x325=805
(7) 在kdb中ps看到pid 805是xxx进程,所以锁的持有者是xxx
阅读(6329) | 评论(1) | 转发(2) |