此方法用于死机故障出现间隔很长,而且不是空指针导致的死机问题.用于查找出现问题的函数.因为这种情况.你不可能花几天甚至几月时间来完成一次调试.不是简单的靠printk函数输出就能解决的了的.

内核死机前的有用的信息主要有下面下个:

CallTrace:
[<f89ef137>]
[<f89eed7e>]
[<c0235ed0>]
[<c01f314a>]
[<c0204460>]
[<c0207337>]
[<c0236e64>]
[<c0227894>]
[<f89ee370>]
[<c0239180>]
[<c01f2d97>]
[<c0239180>]
[<c0239180>]
[<c01f3113>]
[<c0239180>]

这是内核函数的调用栈.最上面的是最后调用的.这个地址为:函数A调用函数B,函数B的下一行语句的地址.有助于定位出问题的函数.

函数B就是出问题的函数.如果地址开头是f8还好问题不是很大这个函数一般来说是你自己写的.如果是C0恭喜你是个内核函数....

Code:8b02833811757b83ec0883c004506a11e8688800

这是出问题的代码的十六进制表示.

接下来你要做的就是定位具体是哪个函数出的问题.如果是函数调用栈的最近地址是f8开头你就把你的内核模块**.o反汇编.如果是c0开头的.你把你设备跑的内核代码编译一次会产生一个vmlinux镜像把它反汇编.

命令:

objdump-Dvmlinux>k.dmp

objdump-Dfw.o>k.dmp.

#vik.dmp

2143:8b02mov(%edx),%eax
2145:833811cmpl$0x11,(%eax)
2148:757bjne21c5<user_ac_policy+0x141>
214a:83ec08sub$0x8,%esp
214d:83c004add$0x4,%eax
2150:50push%eax
2151:6a11push$0x11
2153:e8fcffffffcall2154<user_ac_policy+0xd0>
2158:83c410add$0x10,%esp
215b:85c0test%eax,%eax
215d:7466je21c5<user_ac_policy+0x141>
215f:8b4058mov0x58(%eax),%eax
2162:8945e8mov%eax,0xffffffe8(%ebp)


8b02833811757b83ec0883c004506a11e8688800

错误代码位置定位成功.然后在查找这部分代码在哪个函数里面.

00002084<user_ac_policy>:
2084:55push%ebp
2085:89e5mov%esp,%ebp
2087:57push%edi
2088:56push%esi
2089:53push%ebx
208a:83ec28sub$0x28,%esp
208d:8b550cmov0xc(%ebp),%edx
2090:8b5d08mov0x8(%ebp),%ebx
2093:52push%edx
2094:c745f000000000movl$0x0,0xfffffff0(%ebp)
209b:e8fcffffffcall209c<user_ac_policy+0x18>
20a0:5apop%edx
20a1:59pop%ecx
20a2:50push%eax
20a3:53push%ebx

确定了是user_ac_policy函数的问题具体能确定那一句..就看各位的C语言反汇编代码的阅读能力了....