分享阅读linux内核代码的几个技巧
作者: 2011/4/28 12:44:41
这些技巧都是平时我自已在阅读的时候总结的,想到哪就说到哪了,其实我总结的技巧远不止这些,但是先说这些吧。后面想到了再补充,只有在拿到代码做分析的时候遇到实际的问题时,才能见招拆招,想些办法。
其实linux内核源码还是比较难跟踪的,我刚开始阅读内核源码的时候,感觉很多东西经常找着找着就失去头绪了,很郁闷。
通过一些阅读后发现内核也就那么几招用的比较多,摸清楚其脾气后,剩下的就是耐心了。
1.我曾经用过一阵VI,装了一堆插件后折腾了一阵,发现还是无法感受其推崇者所说的那一堆好处,还是喜欢用sourceinsight。好了,说正题了。首先我们要解决的就是函数或者变量找不到定义地方的问题,表现在sourceinsight上就是那个变量是黑的,到处找不到。
比如我们看们看到:
int bus_register(struct bus_type * bus)
{
...
subsys_set_kset(bus, bus_subsys);
retval = subsystem_register(&bus->subsys);
...
}
其中的bus_subsys。
找了一下bus_subsys找不到定义的地方,肯定是内核和我们躲猫猫,这时候我们可以是否查找一些明显的“定义痕迹”,比如在bus_subsys中的subsys或者说_subsys。果然有新发现。我们找到了这么一个宏。
#define decl_subsys(_name,_type,_uevent_ops) \
struct subsystem _name##_subsys = { \
.kset = { \
.kobj = { .name = __stringify(_name) }, \
.ktype = _type, \
.uevent_ops =_uevent_ops, \
} \
}
得,我们回过头在包含有bus_register的源文件及头文件中查找一下,果然找到了static decl_subsys(bus, &ktype_bus, NULL);这么一行代码。
像这种东西我不是很建议一找不到就直接去网上找,关于内核的文章网上虽然很多,但都不会细到所有的细节都有,你总有独立处理问题的时候,为什么我们不提前让自已多锻炼一下呢?
2.顺序问题,内核有很多的顺序,比如初始化的顺序,比如我们有module_init,__initcall等等,一来编译的时候文件夹和文件有顺序,另外不同的宏包含的东西顺序也是有讲究的,所以在分析模块的时候一定要注意这个,这个东西只能说是注意了,如果对一个模块不熟悉的时候,不可能做到全部都了解,像我有时候也会落下一些东西忘记分析,但是随着看内核的时候越久,内核那些惯用的手法见多了后,就发现不外如是,也就那三瓜子两枣。
3.我们要解决内核运行时那一堆指来指去的指针的问题。这个是我自已调试用的土方法,我就用dump_stack在关键的地方打印出顺序就行了。因为我们做的是嵌入式设备,很多时候不能用KGDB这些高级工具在线调,而且这种方法基本不增加其它的性能开销。
4.有多个定义不知道用哪个。这个基本是因为LINUX支持的CPU比较多造成的。
我们可以用GDB静态分析,也可以用objdump和nm等工具来精确定位一些函数和变量,也可以根据宏来一步一步分析,比如是mips的那么我们就进mips看,这样一步一步来。
5.具备一些意识,你现在面对的是操作系统,不仅仅是只有C文件和头文件的应用,MAKEFILE,链接文件,Kconfig都应该是你的朋友。尤其在看一个模块或者一小部分你感兴趣的代码的时候,首先可以用MAKEFILE和KCONFIG来缩小你需要关注的范围。其实关于MAKEFILE和KCONFIG的重要性,fudan_abc在他那个LINUX那些事之我是USB中强调的比较多,但是说实话,fudan_abc那文章看了玩是挺好玩的,可惜感觉好像看了没啥用,就是知道了一堆概念,不能串起来,我不知道是我的理解能力不行,还是任侨伟同志压根没有讲清楚。呵呵。