诗和远方

Linux内核源码分析方法

Linux内核

Linux内核源码分析方法

https://www.cnblogs.com/fanzhidongyzby/archive/2013/03/20/2970624.html


Linux内核由无数开源社区的“大神们”精心维护,这些人都可以称得上一顶一的代码高手。透过阅读Linux内核代码的方式,我们学习到的不光是内核相关的知识,在我看来更具价值的是学习和体会它们的编程技巧以及对计算机的理解。 

内核源码分析的难度不在于源码本身,而在于如何使用更合适的分析代码的方式和手段。内核的庞大致使我们不能按照分析一般的demo程序那样从主函数开始按部就班的分析,我们需要一种从中间介入的手段对内核源码“各个击破”。这种“按需索取”的方式使得我们可以把握源码的主线,而非过度纠结于具体的细节。 

内核的地位的特殊性决定着内核的执行效率必须足够高才可以响应目前计算机应用的实时性要求,为此Linux内核使用C语言和汇编的混合编程。如何在保证内核高效的前提下提高内核的可维护性,这需要依赖于内核中那些“优美”的设计。 

在一般的应用软件设计领域,编码的地位可能不被过度的重视,因为开发者更注重软件的良好设计,而编码仅仅是实现手段问题。但是这在内核中并不成立,好的编码设计带来的不光是可维护性的提高,甚至是代码性能的提升。

内核代码处理的信息多数和计算机底层密切相关。比如操作系统、编译器、汇编、体系结构等相关的知识的欠缺,会让阅读内核代码障碍重重。

面对大量的并且复杂的内核代码,如果不从全局的角度入手,很容易陷入代码细节的泥淖中。内核代码虽然庞大,但是它也有它的设计原则和架构,如果我们理清代码模块的整体设计思路,再去分析代码的实现,可能分析源码就是一件轻松快乐的事情了。

内核代码分析首先我们需要定位要分析的代码涉及的内容。是进程同步和调度的代码,是内存管理的代码,还是设备管理的代码,还是系统启动的代码等等。内核的庞大决定着我们不能一次性将内核代码全部分析完成,因此我们需要给自己一个合理的分工。正如算法设计告诉我们的,要解决一个大问题,首先要解决它所涉及的子问题。

Linux源码提供的文档、注释和源码标识符的名称(不要小看代码中的标识符的命名,有时它们能提供关键的信息)。

假定我们要分析Linux的变频机制实现的代码。目前为止我们仅仅是知道这个名词而已,透过字面含义我们可以大致猜测它应该和CPU的频率调节相关。通过信息搜集,我们应该能得到如下的相关的信息:

1.CPUFreq机制。

2.performance、powersave、userspace、ondemand、conservative调频策略。

3./driver/cpufreq/。

4./documention/cpufreq。

5.P state和C state。

……

分析Linux内核代码如果能搜集到这些信息,应该说是非常“幸运”了。毕竟有关Linux内核的资料确实不如JQuery那么丰富。


源码定位

从资料搜集中,我们“有幸”找到了源码相关的源码目录。但是这并非意味着我们的确就是分析这个目录下的源代码。有时我们找到的目录有可能是分散的,也有时我们找到的目录下有很多和具体机器相关的代码,而我们更关心的是待分析代码的主要机制,而非与机器相关的特化代码。

因此,我们需要对资料中涉及代码文件的资料进行仔细甄选。

只要能抓住大多数模块相关的核心源文件,通过后期对代码的具体分析,就很自然的把它们全部找出来。

回到上述的例子中,我们认真的阅读/documention/cpufreq下的文档说明。目前的Linux源码会把模块相关的文档说明保存在源码目录的documention的文件夹下,如果待分析的模块没有文档说明,这多少会增加定位关键源码文件的难度,但是不会导致我们找不到我们要分析的源码。通过阅读文档说明,我们至少能关注到/driver/cpufreq/cpufreq.c这个源文件。通过这个对源文件的文档说明,结合之前搜罗到的调频策略,我们很容易关注到cpufreq_performance.c、cpufreq_powersave.c、cpufreq_userspace.c、cpufreq_ondemand、cpufreq_conservative.c这五个源文件。所有涉及的文件都找完了吗?不用担心,从它们开始分析,迟早能找到其他的源文件。如果在windows下使用sourceinsight阅读内核源码的话,我们通过函数的调用和查找符号引用等功能,结合代码的分析可以很方便的找到另外的文件freq_table.c、cpufreq_stats.c和/include/linux/cpufreq.h。

按照搜索出的信息流动方向,我们完全可以定位到需要分析的源码文件。源码定位这一步并非十分关键,因为我们不需要找出所有源码文件,我们可以把部分工作推迟到分析代码的过程中。源码定位也比较关键,找到一部分源码文件是分析源码的基础。



简单注释

在已定位好的源码文件中,分析每个变量、宏、函数、结构体等代码元素的大致含义和功能。之所以称此为简单注释,并非指这部分的注释工作很简单,而是指这部分的注释可以不必过分细化,只要大致描述出相关代码元素的含义即可。相反,这里的工作其实是整个分析流程中最困难的一步。因为这是第一次深入到内核代码的内部,尤其是对于首次分析内核源码的人来说,大量的生疏GNU的C语法和铺天盖地的宏定义会令人很绝望。此时只要沉下心来,弄清每个关键的难点,才能保证以后碰到类似的难点不会再被困住。而且,我们对内核相关的其他知识会不断的像树一样扩展开来。

比如在cpufreq.c文件开始就会出现“DEFINE_PER_CPU”宏的使用,我们通过查阅资料可以基本弄清这个宏的含义和功能。这里使用的手段和之前搜集资料使用的方法基本一致,另外我们也可以使用sourceinsight提供的转到定义等功能查看它的定义。

我们也不要强求一次就能把注释描述的很准确(我们甚至都没必要弄清每个函数的具体实现流程,只要弄清大致功能含义即可),我们结合搜集到的资料和后边代码的分析不断的完善注释的含义(源码中原有的注释和标识符命名在此很有利用价值)。通过不断的注释,不断的查阅资料,不断的修改注释的含义。


详细注释

完成代码的简单注释后,可以认为对模块的分析工作完成了一半了,剩下的内容就是对代码的深入分析和彻底理解。简单注释总是不能将代码元素的具体含义描述的十分精确,因此详细注释是十分有必要的。这一步中,我们需要弄清以下内容:

变量定义在何时被使用。

宏定义的代码何时被使用。

函数的参数和返回值的含义。

函数的执行流程和调用关系。

结构体字段的具体含义和使用条件。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Catalog
标签列表
最新
最热
常用网站
站点信息
  • 文章总数:2016
  • 页面总数:1
  • 分类总数:17
  • 标签总数:518
  • 评论总数:0
  • 浏览总数:592287
Archives
Copyright © 2017-2019 www.my889.com Some Rights Reserved.
推荐使用 Chrome 浏览器浏览本站
沪ICP备17052342号
Sitemap XML