阅读源码方法汇总

Table of Contents

1 源码选择

如果只是单纯学习源码阅读,尽量学不需要太多背景的源码来做分析,因为选择需要有背景知识的源码成本就要高点,比如你要分析Apache的源码,就得学Apache。有时候并不需要完整读完整套源码,可能只会分析一小块地方,比如你可能只会分析Linux文件系统怎么实现,而不会去读完整个源码。

带有目的去阅读源码效果为佳,比如:

去深入理解项目中用到的库;

解决遇到一些坑;

结合到理论知识学习,比如学习操作系统、算法、RFC文档等;

学习新的编程模式;

学习别人的编程风格;

满足某些开发需求;

了解工具实现原理;

挖漏洞;

...

2 让源码能编译并工作起来

源码分析的第一步不是用编辑器硬读代码,最重要的起步就是:先学会用它。

如果是软件,就先学会怎么用(成功编译、使用)。如果是库,一般通过以下几个方式就能学会使用:

  • 官方文档
  • 相关书籍。并不是每个库都有清晰的文档,如果文档看不懂,最好能借助相关书籍。
  • 代码仓库里的一些示例代码
  • 单元测试

3 入口

先从入口开始看,比如C语言的main函数,如果是API的话,就直接看API的代码。

有个技巧——运行时打印出函数调用的过程,比如Python可通过下面方式查看函数调用流程:

python -m trace –trackcalls [文件名]

不同的语言和库有不同的方式,甚至可以用单步断点等方法。

另外,同时观察:

  • 包含了哪些头文件、导入的哪些库,从而了解文件大概实现原理;
  • 全局变量;
  • 使用方法(Usage)和参数处理。

4 工具

Source Insight是一款运行在Windows上的商业源码检索工具,由于不跨平台,并且费用昂贵,很长一段时间我都在研究开源的代替方案,测试中发现OpenGrok和GNU GLOBAL很好用。

4.1 OpenGrok和GNU GLOBAL

有一些源码检索工具对于Linux内核这类规模的源码检索就存在性能问题,而OpenGrok和GNU GLOBAL这两款开源的源码检索十分好用,大大小小的项目都适用。

OpenGrok有一个Web界面,把源码索引搭在服务器上用Web来看源码非常方便,甚至有时在客厅用iPad看源码。详细的请见:https://github.com/OpenGrok/OpenGrok

GNU GLOBAL生成索引数据,很多编辑器都有支持的插件,如Emacs和Vim。同时它也可以在命令行下使用。官网:http://www.gnu.org/software/global/

GNU GLOBAL使用举例:

在项目目录下运行gtags命令生成索引。

global命令负责符号检索:

例,要查找main函数的位置:global main
例,查找main函数在哪些文件中被引用过:global -r main
例,更新索引:global -u,这个命令可以配置在Emacs中间隔一段时间就运行一次

4.2 其他工具

  • 小项目用Ctags和Emacs自带的Etags
  • IDE:PyCharm社区版,IDEA社区版
  • 思维导图
  • 纸和笔,边看代码边画流程图,这是最顺手也最快捷的方法。

其他还有一些:

  • Doxygen,生成函数调用关系图
  • Argouml,UML绘制工具

运行时的工具:

  • GDB
  • Strace/Dtrace
  • SystemTap

5 了解架构

好的软件都有好的架构,要学了解常用的软件架构。Project有别于脚本,脚本代码相对来说较随意,Project更有组织性。

  • 设计模式和OOP,分析类之间是如何组织的;
  • 自动构建,比如Makefile,还有Java的Ant等等,并且分析它们在项目里是如何组织代码的;
  • 模块划分,根据项目文档或者目录组织,了解划分的模块;
  • 编程风格约定;
  • 常见的数据结构,如链表、队列等。

有时候不要纠结在某个函数的算法上,否则浪费很多时间的,清楚这个函数是干嘛的,输入什么,输出什么就OK了。后面追究细节的时候再来看这个具体实现也不错。项目太大可以不用看完整体源码,看关注的那部分模块即可。

6 了解一个函数的功能

  1. 最基本的,从函数名是否能读出函数的功能;
  2. 看函数的头注释;
  3. 是否有文档;
  4. 测试用例;
  5. 看看哪些地方调用了它,以及是如何调用的。

7 使用调试器

学会了解软件在运行时候的动态,代码是一个样,运行的时候又是另外一个样子,所以要学会用调试器,学会调试软件,在不懂的地方可以下断点,或者在某些地方打印某些东西,看源码也可以边修改边理解。

8 遇到问题

  1. 记录下来,反复阅读源码,回头再看;
  2. 不要纠结细节,明白这里干嘛的即可,回头再看;
  3. 不懂的地方去Google,如果遇到语言语法问题,去学习;
  4. 实在不行问别人吧。