, 设置在 sys 文件系统的某个文件中. 当文件中的值变化时, 通知内核执行相应的代码.
2.6.3 使用统计量观察内核执行某段代码的频率
实现思路就是在内核中的设置一个全局变量, 比如 my_count, 当内核执行到某段代码时, 给 my_count + 1 就行.
同时还要将 my_count 打印出来(可以用printk), 便于随时查看它的值.
2.6.4 控制内核执行某段代码的频率
有时侯, 我们需要在内核发生错误时打印错误相关的信息, 如果这个错误不会导致内核崩溃, 并且这个错误每秒会发生几百次甚至更多.
那么, 用printk输出的信息会非常多, 给系统造成额外的负担.
这时, 我们就需要想办法控制错误输出的频率, 有2种方法:
方法1: 隔一段时间才输出一次错误
static unsigned long prev_jiffy = jiffies; /* 频率限制 */ if (time_after(jiffies, prev_jiffy + 2*HZ)) { /* 输出间隔至少 2HZ */ prev_jiffy = jiffies; printk(KERN_ERR "错误信息....\n"); }
方法2: 输出 N 次之后, 不再输出(N是正整数)
static unsigned long limit = 0; if (limit < 5) { /* 输出5次错误信息后就不再输出 */ limit++; printk(KERN_ERR "错误信息....\n"); }
2.7 二分法查找bug发生的最初内核版本
在内核发生了bug之后, 如果能够知道是bug从哪个内核版本开始出现的, 那对修正这个bug会有很大的帮助.
由于内核代码非常庞大, 即使用二分查找法, 手工去找哪个版本开始出现bug的话, 仍然是非常耗时和繁琐的.
好在 Git 给我们提供了一个非常有用的二分搜索机制.
git bisect start # 开始二分搜索 git bisect bad <bad_revision> # 指定一个bug出现的内核版本号 git bisect good <good_revision> # 指定一个没有bug的内核版本号, 此时git会检测2个版本直接的隐患 # 根据结果再次设置 bad 和 good 的版本号, 缩小Git检索范围, 直至找到可疑之处为止.
2.8 社区
当你在调试bug时用尽了一切手段仍然无济于事时, 可以考虑求助linux社区, 求助时注意一定要描述清楚bug的状况.
(可以参考一下别人汇报bug的格式)
linux 内核相关的邮件列表非常多: 参见 http://vger.kernel.org/vger-lists.html
和内核开发, bug汇报相关的邮件列表参见: http://vger.kernel.org/vger-lists.html#linux-kernel (这个邮件列表非常活跃, 每天的邮件都非常多!!!)
3. 总结
linux内核调试必须要依靠大量的实践来掌握, 仅仅靠上面介绍的一些技巧还远远不够, 只有实实在在的去阅读内核代码, 实实在在的去修正一个个bug, 才算真正掌握内核, 真正了解内核.
多看看之前linux内核bug的修正案例, 也是个不错的积累经验的方法.
PS.
对于初学者来说, 在真机上做内核开发动辄导致机器崩溃(panic), 非常麻烦. 现在的虚拟机这么强大, 建议都在虚拟机上测试linux内核修改的效果.
我之前的关于<<Linux内核设计与实现>>笔记的博客中的代码都是在虚拟机上运行测试的.