现在的位置: 首页 > 综合 > 正文

内核模块捉虫记

2013年06月25日 ⁄ 综合 ⁄ 共 1119字 ⁄ 字号 评论关闭

Bug调试了好几天了,周一周二,昨天调试了一整天,从9点到23点,今天从9点到15点30左右。
原来就发现在关闭VLC的时候,有时会导致死机, 一直到昨天反复尝试了好多次,确定是停止发数据一会儿(几秒以上),然后关闭VLC就会死机(机器无响应,键盘Caps Lock和Scroll Lock灯一齐闪),以前也遇到过,应该是内核里出了问题。  Skype的话,结束通话也会死机。 两者比较类似。 怀疑是死锁之类的问题(因为机器没反应,两个灯在闪,好像以前出现过,但忘记原因是什么,仅凭感觉觉得像死锁,后来证明男人的直觉是不准的),不知道尝试了多少次之后,添加一些debug用的printk,同时用wireshark做验证,发现VLC和Skype结束通话的时候,还会发出一些包,VLC是发送1个前边包的一个Fragment IP包,外加1个UDP包,载荷都是0。 但是一次性直接关掉程序的时候,却不会死机,这个时候,最后的包是跟前边的数据包一起在一个时间槽(刷新周期)内一起处理的。 昨天晚上,注释掉向PSList加入端口,不会死机,说明问题存在监测这边。
        周五(今天)早上,尝试让远端机器不发送ACK包,也不会死机,再次说明与监测模块有关。 还是怀疑PSList的读写互斥上有问题,因为这里的锁没有加太多;还是一步一步加printk,一次次试验、重启、看/var/logs/messages里存的上次死机前的log,发现程序走到了接收到了远端主机发送最后那个包的ACK,并处理完成了。 但是,到这就没了,那下一步到哪里? 问题在哪里发生的呢?困惑。
         转念一想,咦。。。syslogd在崩溃的时候不一定能记录到最后一条printk的输出吧,那么,程序应该还是能够运行到RCN_CompSeq(),但printk输出没法记录,恩,先检测下这个函数,改点删除PSList节点的代码,一运行死机了,哦,只注释了删除节点,改后for循环没照顾到,似乎是死循环了,但是刚刚死机的症状也是2个灯齐闪,恩,那么也许不是死锁,仔细阅读代码,啊哈,原来真的是分母为0导致的,弄了这么久!
         一是因为是内核,没有提示,只会死机;二来是边界条件,在只收一个包的情况下会出现这个问题。

 

debug小结:

下心来,好好分析,耐心review代码 (printk/f 是好朋友)
一口气连续弄,但要适当短暂停止/休息,防止脑袋晕掉,暂停不宜太长,比如一天
思路要开阔,有时要怀疑下自己做的假设(意识到自己做了些假设)
与其他人交谈,会有启示

如何写高效代码呢?

写完一个函数,仔细走一遍, 考虑下边界条件和异常处理(只有一个包会怎样? 数组越界? 除以0等)

单元测试

 

实践 & 总结

抱歉!评论已关闭.