Linux内核开发流程指南 - 7. 高级主题【ChatGPT】

发布时间 2023-12-08 20:19:04作者: 摩斯电码

高级主题

到目前为止,希望你已经掌握了开发过程的工作方式。然而,还有更多需要学习的地方!本节将涵盖一些对于希望成为 Linux 内核开发过程中的常规部分的开发人员有帮助的主题。

7.1. 使用 git 管理补丁

内核对分布式版本控制的使用始于 2002 年初,当时 Linus 首次开始尝试专有的 BitKeeper 应用程序。虽然 BitKeeper 颇具争议,但它所体现的软件版本管理方法绝对不是。分布式版本控制使得内核开发项目立即加速。在当前时代,有几种免费的 BitKeeper 替代品。不管好坏,内核项目已经确定 git 作为其首选工具。

使用 git 管理补丁可以让开发人员的生活变得更加轻松,特别是在补丁数量增多的情况下。然而,git 也有其不足之处和一定的危险性;它是一个年轻而强大的工具,仍在被其开发人员不断完善。本文档不会试图教读者如何使用 git;这本身就足够成为一份长文档的材料。相反,这里的重点将放在 git 如何特别适用于内核开发过程上。希望快速掌握 git 的开发人员可以在以下网址找到更多信息:

以及网络上的各种教程。

首要任务是阅读上述网站,并在尝试将补丁提供给他人之前,对 git 的工作原理有扎实的理解。使用 git 的开发人员应该能够获取主线仓库的副本,查看修订历史,提交更改到树中,使用分支等。对 git 的历史重写工具(如 rebase)的理解也是有用的。Git 有其自己的术语和概念;git 的新用户应该了解引用(refs)、远程分支、索引(index)、快进合并(fast-forward merges)、推送和拉取(pushes and pulls)、分离头等。一开始可能有些令人生畏,但通过一些学习,这些概念并不难理解。

在快速掌握 git 的过程中,使用 git 生成通过电子邮件提交的补丁可以是一个不错的练习。

当你准备好开始发布供他人查看的 git 树时,当然需要一个可以被拉取的服务器。如果你有一个可以接入互联网的系统,使用 git-daemon 设置这样的服务器相对简单。否则,网络上开始出现了一些免费的公共托管站点(例如 Github)。已经成熟的开发人员可以在 kernel.org 上获得账户,但这并不容易;更多信息请参阅 https://kernel.org/faq/

正常的 git 工作流程涉及使用大量的分支。每条开发线都可以分离成一个独立的“主题分支”并独立维护。在 git 中,分支是廉价的,没有理由不充分利用它们。而且,无论如何,你不应该在打算请他人拉取的任何分支中进行开发。公开可用的分支应该谨慎创建;只有当补丁从开发分支合并完整并准备就绪时,才应该合并到公开分支中。

Git 提供了一些强大的工具,可以让你重写开发历史。一个不方便的补丁(比如破坏二分法的补丁,或者有其他明显 bug 的补丁)可以在原地修复,或者从历史中完全消失。一个补丁系列可以被重写,就好像它是在今天的主线之上编写的一样,尽管你可能已经在上面工作了数月。更改可以在不同分支之间透明地移动。等等。谨慎使用 git 的历史修订能力可以帮助创建更干净的补丁集,减少问题。

然而,过度使用这种能力可能会导致其他问题,超出了简单追求完美项目历史的范畴。重写历史将重写其中包含的更改,将经过测试(希望如此)的内核树变成未经测试的。但更重要的是,如果开发人员没有共享的项目历史视图,他们就很难进行合作;如果你重写了其他开发人员已经拉取到他们仓库中的历史,那么你将给这些开发人员带来更多困难。因此,在这里适用一个简单的经验法则:已经导出给他人的历史在此后通常应被视为不可变的。

因此,一旦你将一组更改推送到你的公开可用服务器上,这些更改就不应该被重写。如果你尝试推送不会导致快进合并的更改(即不共享相同历史的更改),git 将尝试强制执行此规则。虽然可以覆盖此检查,但有时可能需要重写已导出的树。在 linux-next 中移动更改集以避免冲突就是一个例子。但这样的操作应该很少见。这也是为什么开发应该在私有分支中进行(如果需要,可以进行重写),只有在其处于相当先进状态时才移入公共分支。

随着主线(或其他基于一组更改的树)的推进,诱人的做法是与该树合并以保持在前沿。对于私有分支,rebase 可能是保持与其他树同步的简便方法,但一旦树被导出到世界上,rebase 就不再是一个选项。一旦发生这种情况,必须进行完整的合并。偶尔进行合并是有道理的,但过于频繁的合并可能会不必要地使历史混乱。在这种情况下,建议的技术是偶尔进行合并,通常只在特定的发布点(例如主线 -rc 发布)上进行。如果你对特定更改感到紧张,你可以在私有分支中进行测试合并。git 的 "rerere" 工具在这种情况下可能会有用;它会记住如何解决合并冲突,这样你就不必重复相同的工作。

关于像 git 这样的工具的最大的反复投诉之一是:从一个仓库移动补丁到另一个仓库使得很容易悄悄地插入不明智的更改,这些更改可能会在审查雷达下进入主线。当内核开发人员看到这种情况发生时,他们往往会感到不快;发布一个带有未经审查或与主题无关的补丁的 git 树可能会影响你将来拉取树的能力。引用 Linus 的话:

你可以给我发送补丁,但是要让我从你那里拉取一个 git 补丁,我需要知道你知道自己在做什么,并且我需要能够信任事情 而不必 去逐个手动检查每个变更。

https://lwn.net/Articles/224135/)。

为了避免这种情况发生,确保给定分支中的所有补丁都与相关主题密切相关;一个“驱动程序修复”分支不应该对核心内存管理代码进行更改。最重要的是,不要使用 git 树来绕过审查过程。偶尔向相关列表发布树的摘要,并在合适的时候请求将树包含在 linux-next 中。

如果其他人开始发送补丁以纳入你的树中,不要忘记审查它们。还要确保保持正确的作者信息;git 的 "am" 工具在这方面尽力而为,但如果补丁是通过第三方转发给你的,你可能需要为补丁添加一个 "From:" 行。

在请求拉取时,确保提供所有相关信息:你的树在哪里,要拉取哪个分支,以及拉取将导致哪些更改。git 的 request-pull 命令在这方面可能会有所帮助;它会按其他开发人员的期望格式化请求,并还会检查你是否已经记得将这些更改推送到公共服务器上。

7.2. 审查补丁

一些读者肯定会因为即使是初学者的内核开发人员也应该审查补丁而对将这一部分放在“高级主题”下提出异议。毫无疑问,通过查看他人发布的代码来学习如何在内核环境中编程是没有比这更好的方法了。此外,审查人员总是供不应求的;通过查看代码,你可以对整个过程做出重要贡献。

审查代码可能是一项令人望而生畏的任务,特别是对于一个可能会因为质疑由经验更丰富的人员发布的代码而感到紧张的新内核开发人员。然而,即使是由最有经验的开发人员编写的代码也可以改进。也许对于审查人员(所有审查人员)来说,最好的建议是:将审查意见表述为问题,而不是批评。询问“在这条路径中锁是如何释放的?”总是比陈述“这里的锁定是错误的”更有效。

不同的开发人员会从不同的角度审查代码。有些人主要关注编码风格和代码行是否有尾随空格。其他人则主要关注补丁所实现的整体变更对内核是好事还是坏事。还有一些人会检查问题锁定、过多的堆栈使用、可能的安全问题、代码在其他地方的重复、充分的文档、对性能的不利影响、用户空间 ABI 的更改等。如果所有类型的审查都能带来更好的代码进入内核,那么它们都是受欢迎和值得的。