中年如何高效阅读代码?Linux大神拍了拍你并教给你这三个步骤( 七 )


接下来重点关注补丁的正文区 。 一个补丁文件可以涉及多个源代码文件 , 每个涉及的源代码文件可以包含多处变更 。 因此补丁正文区的内容包括三大部分:总体概述(修改了哪些源文件 , 增加了多少行 , 删除了多少行) , 文件路径描述(以diff开头的连续四行 , 其中以---开头的表示旧版本中的源文件路径 , 以+++开头的表示新版本中的源文件路径) , 若干个变更区段(以@@开始的若干行) 。 变更区段是补丁内容的最小单位 , 图2所示的补丁仅涉及一个源代码文件的一处变更 , 也就只有一个变更区段 。
变更区段的内容有四种行:定位行 , 上下文行 , 删除行 , 增加行 。 定位行就是以@@开头的行 , 其中的4个数字分别是变更区段在旧版本源文件中的起始行号/总行数以及在新版本源文件中的起始行号/总行数 。 起始行号允许一定的误差 , 因此需要配合上下文(区段的前三行与后三行 , 以及区段中其他以空格开头的行)进一步确定区段的位置;总行数则不允许有任何误差 , 否则会被认为是一个非法补丁 。 区段中以-开头的行是删除行 , 代表旧版本源文件里面有而新版本源文件里面没有的行;以+开头的行是增加行 , 代表旧版本源文件里面没有而新版本源文件里面有的行 。
那么图2中这个补丁究竟包含了什么信息呢?现在我们可以知道了:
它来自Git代码库中一次哈希值为dee809bfaa4caedb56cbc4d842ecf85acbbdb3e1的Commit , 该Commit标题是“drm/amdgpu: Set a suitable dev_info.gart_page_size” , 源代码补丁的作者是Rui Wang &ltwangr@lemote.com&gt和Huacai Chen &ltchenhc@lemote.com&gt , 其中后者同时也是邮件的发送人 。 这个补丁修改了源代码文件drivers/gpu/drm/amd/amdgpu/ amdgpu_kms.c , 修改的位置在旧版源文件和新版源文件的第717行左右 , 该区段在变更前和变更后的代码行数均为7行 。 这次变更删除了一行代码:
dev_info.gart_page_size = AMDGPU_GPU_PAGE_SIZE
同时又在原来的位置增加了一行代码(实质上就是修改了一行代码):
dev_info.gart_page_size = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE)
实际的内核开发过程中 , 代码补丁往往比这个例子要复杂很多 , 但是其原理是相同的 。 理解了补丁文件的原理 , 在阅读源代码及其变更历史的时候就会如虎添翼 。 例如 , 我们已经知道Linux-3.15版本的内核加入了龙芯3A的支持 , 但是如果直接查看Linux-3.15的完整源代码 , 你会发现相关的代码延伸非常广泛 , 遍及到多个子系统 , 几十个目录 , 上百个文件 。 面对这种情况 , 想要在一个早期的内核版本上移植相同的功能 , 简直无从下手 。 那么 , 如何才能“干净利落”又“完整无缺”地分离出那些跟龙芯3号有关的一项项功能呢?答案就是:查看git记录 , 导出系列补丁 , 然后按顺序逐个分析解读 。 在理解这一系列补丁的基础上 , 如果你需要在一个早期的内核版本(如Linux-3.12)上添加龙芯3号的支持 , 并不会是一件非常困难的事情 。
结语 基于“广度优先”的大原则 , 首先找准代码的入口点 , 从源头开始梳理代码框架;其次理清主脉络 , 通过精简代码 , 只保留源码最核心的内容;最终可根据函数名了解各个模块的功能 , 厘清代码的实现逻辑 , 同时为了使得阅读更加方便 , 还介绍了树形视图和链式视图 。 通过结合具体的案例 , 本文详细解析了“三部曲”的具体实现方法 , 并且介绍了补丁文件的阅读方式 。
中年如何高效阅读代码?Linux大神拍了拍你并教给你这三个步骤
本文插图
这一套方法不仅贯穿在我的实际工作中 , 也是《用“芯”探核:基于龙芯的linux内核探索解析》一书中绝大部分代码解析的方法 , 使得本书更方便读者阅读和理解 。


推荐阅读