Chinaunix

标题: 浅谈内核源码研究方法 [打印本页]

作者: comba_sellie    时间: 2013-01-20 14:39
标题: 浅谈内核源码研究方法
本帖最后由 comba_sellie 于 2014-08-12 19:12 编辑

介绍自己研究源码中所使用的工具及方法,希望对大家有帮助。

1.选择合适的源码阅读工具
我选择的工具是Source Insight-v3.50.0066。
Source Insight这个工具应该不用介绍吧,Windows平台上公认最好的源码阅读工具(不确定是不是公认 )。使用方法就不说了,大家可以问百度后再自己实操。
主要使用到以下一些功能:
1.reference trees
2.call trees
3.smart rename
4.macro
5.Edit condition
6.强大的搜索功能

下面是source insight设置的效果图(背景设置成灰色,眼睛不易疲劳,VC-style,大家可以按自己喜好设置)

所用的配置文件(将后缀名.gz去掉)
GLOBAL.CF3.gz (129.85 KB, 下载次数: 152)

2.新建工程并添加内核源码
如果把内核所有文件添加进来,阅读过程中会遇到许多同名的函数(因为kernel支持不同架构,同名函数在不同架构下的实现),此时寻找该函数实现就会变得困难,
而且由于添加所有文件将使工程变得臃肿,搜索速度变慢,影响阅读效率。这里我对内核的头文件及源文件进行了筛选,只添加那些确实编译进内核的文件。
具体原理是解析内核编译过程中生成的*.cmd文件
操作步骤:
1)下载script.zip script.zip (962 Bytes, 下载次数: 249)
2)过滤内核编译文件
编译内核(如果编译过了,这步可忽略),确保生成*.cmd文件。
解压出两个shell脚本,将其放置在内核源码根目录下运行。
运行完后会在内核源码根目录下生成两个文件和一个文件夹。
其中kernel-header.txt kernel-src.txt是内核编译用到的头文件及源文件列表
other-file-header存放的是编译script下的源文件时用到的头文件,头文件来源: /usr/include及gcc编译器目录下的头文件
将这两个文件及一个文件夹拷贝至Source Insight内核工程目录下(这里要注意,创建Source Insight内核工程时需要将目录设置为内核源码目录,否则后面操作会失败)
3)添加文件
打开Source Insight的内核工程
打开Project->Add and Remove Project Files...->Add from list...
选择kernel-src.txt
选择kernel-header.txt
选择other-file-header目录
->Add All 将other-file-header目录的头文件添加进工程

3.开始遨游内核源码之旅
从head.S第一条指令到start_kernel,每个架构实现都不一样,这里就不细说。
这里主要说明一下start_kernel()->rest_init()->kernel_init()->do_basic_setup()->do_initcalls() 这个函数的重要性
该函数功能: 运行内核各个组件的初始化函数。(实现原理可参考《Linux内核协议栈源码解析V0.1.pdf》中的Link Scripts知识)
用下面指令过滤后即为do_initcalls的执行流程
readelf -s -W vmlinux|grep initcall|sort -k 2
可以选择自己感兴趣的内核组件开始研究。
阅读过程中会遇到许多函数指针调用如:
/* socket.c中socket系统调用代码 */
err = pf->create(net, sock, protocol);
此时就不能一眼看出到底调用的那个函数,一般函数指针会在初始化阶段赋值,此时就得去阅读初始化代码并将其转换成Visio图。
Visio特别适合画数据结构关系图,函数流程图,有图在手再也不用烦恼函数指针不知指向何处了,这样即使过很久后二次阅读也能很快理解代码实现。
下图是我研究过程中画的Visio图
network.zip (3.05 MB, 下载次数: 1273)
根文件系统的挂载过程.zip (37.25 KB, 下载次数: 153)

就扯这么多。

第二次编辑:
更新了脚本
添加了内核condition解析代码
添加了uboot相关的内容
linux-parse.rar (10.58 KB, 下载次数: 1513)
作者: evilhacker    时间: 2013-01-20 15:12
唔。。。。买不起正版的Source Insight
作者: Godbach    时间: 2013-01-20 21:57
回复 1# comba_sellie
感谢 LZ 分享


   
作者: luoyan_xy    时间: 2013-01-21 21:57
  感谢分享,那个提取源文件的方法不错。

  不知道有没有方法能够把只有包含那些确定包含的编译选项宏所定义的代码提取进来呢,内核里那么多条件编译。。。
作者: comba_sellie    时间: 2013-01-21 22:56
回复 4# luoyan_xy
有写过一个Source Insight的宏,但是还不完善,只能解析autoconf.h中
#define CONFIG_XX 1
#define CONFIG_XX 0
两种情况

   
作者: dingyujie    时间: 2013-01-22 10:56
回复 2# evilhacker


    谁用正版?序列号一搜一大把。附我的SI:

作者: tempname2    时间: 2013-01-22 13:02
看情况吧,有些公司里,被IT部门查到用盗版就high了。
作者: daniel_11    时间: 2013-01-22 16:17
有公司还被发warning letter!!!
作者: comba_sellie    时间: 2014-08-12 19:13
擦 重新编辑后居然不重新排列 只好自己来了
作者: Tinnal    时间: 2014-08-12 21:38
回复 1# comba_sellie

很好,针对内核代码的阅读问题,网上确定没有非常好的工具,目前来说只能SI最适合了。但毕竟内核有大量的指针引用、重名函数、宏拼接。因此我自己想打算自己做一个内核专用的分析工具出来。现在正在做源码解释部份,已经在github上注册项目了,目前因为还不成熟,先不把项目公开。
稍微成熟,希望你能参与进来。
   
作者: comba_sellie    时间: 2014-08-12 22:40
回复 10# Tinnal
好啊 到时候记得@我
作者: oldboy151    时间: 2016-04-28 00:41
LZ,感谢分享,但是我运行了你那两个脚本,但是却提示readlink: invalid option --e,这是什么问题啊,求指点
作者: nswcfd    时间: 2016-05-06 18:05
       -e, --canonicalize-existing
              canonicalize by following every symlink in every component of the given name recursively, all components must exist

也许不是所有平台下都支持-e选项,它的目的是把路径上的所有符号链接都展开,实在不行用脚本模拟一个也可以。
作者: comba_sellie    时间: 2016-05-12 15:47
我的博客上有最新的版本。
作者: goldenratio713    时间: 2016-06-29 09:51
楼主,谢谢您的分析!能否说下,linux_kernel_condition_parse.c怎么用?还有hash.c




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2