7. 高级主题¶
到目前为止,希望您已经掌握了开发流程的工作原理。但是,仍然有更多需要学习的地方!本节将介绍一些主题,这些主题对于希望成为 Linux 内核开发过程常规参与者的开发人员来说很有帮助。
7.1. 使用 git 管理补丁¶
内核对分布式版本控制的使用始于 2002 年初,当时 Linus 首次开始使用专有的 BitKeeper 应用程序。虽然 BitKeeper 存在争议,但它所体现的软件版本管理方法肯定不是。分布式版本控制立即加速了内核开发项目。在当前时代,有几种免费的 BitKeeper 替代方案。无论好坏,内核项目都已将 git 作为其首选工具。
使用 git 管理补丁可以使开发人员的生活更加轻松,尤其是当补丁的数量增加时。Git 也有其粗糙之处,并存在某些危险;它是一种年轻而强大的工具,仍在被其开发人员改进。本文档不会尝试教读者如何使用 git;这本身就足以成为一篇很长的文档。相反,这里的重点将是 git 如何融入特定的内核开发过程。希望快速上手 git 的开发人员可以在以下位置找到更多信息:
以及在网络上找到的各种教程。
首要任务是阅读以上站点,并在尝试使用它来向其他人提供补丁之前,对 git 的工作原理有扎实的理解。使用 git 的开发人员应该能够获取主线存储库的副本、浏览修订历史、将更改提交到树中、使用分支等。了解 git 的历史重写工具(例如 rebase)也很有用。Git 有自己的术语和概念;git 的新用户应该了解 refs、远程分支、索引、快进合并、推送和拉取、分离的 HEAD 等。一开始可能会有点吓人,但经过一些学习,这些概念并不难掌握。
在使用 git 来为通过电子邮件提交生成补丁时,可以进行良好的练习,从而加快速度。
当您准备好开始将 git 树提供给其他人查看时,您当然需要一个可以从中拉取的服务器。如果您的系统可以访问互联网,使用 git-daemon 设置这样的服务器相对简单。否则,免费的公共托管站点(例如 Github)开始出现在网络上。已建立的开发人员可以在 kernel.org 上获得一个帐户,但这些帐户不容易获得;有关更多信息,请参见 https://linuxkernel.org.cn/faq/。
正常的 git 工作流程涉及大量分支的使用。每一行开发都可以分为单独的“主题分支”并独立维护。git 中的分支很便宜,没有理由不自由使用它们。而且,在任何情况下,您都不应该在任何您打算请求其他人从中拉取的分支中进行开发。应谨慎创建公开可用的分支;当补丁处于完整形式并准备就绪时,从开发分支合并补丁 - 而不是提前合并。
Git 提供了一些强大的工具,可以让您重写开发历史。不方便的补丁(例如,破坏了对分查找的补丁或具有其他某种明显错误的补丁)可以就地修复或从历史中完全消失。补丁系列可以重写,就好像它是基于今天的主线编写的一样,即使您已经使用了数月。可以透明地将更改从一个分支转移到另一个分支。等等。明智地使用 git 的修订历史能力可以帮助创建更干净、问题更少的补丁集。
但是,过度使用此功能可能会导致其他问题,除了对创建完美项目历史的简单痴迷之外。重写历史将重写该历史中包含的更改,从而将经过测试(希望如此)的内核树变成未经测试的内核树。但是,除此之外,如果开发人员对项目历史没有共同的看法,他们就无法轻易协作;如果您重写了其他开发人员已拉入其存储库的历史,那么您将使这些开发人员的生活变得更加困难。因此,这里适用一个简单的经验法则:已导出给其他人的历史通常应被视为不可变的。
因此,一旦您将一组更改推送到公开可用的服务器,就不应重写这些更改。如果您尝试推送不会导致快进合并的更改(即,不共享相同历史的更改),Git 将尝试强制执行此规则。可以覆盖此检查,并且有时可能需要重写导出的树。在 linux-next 中移动更改集以避免冲突就是一个例子。但是,此类操作应该很少见。这也是为什么应该在私有分支中进行开发(必要时可以重写),并且只有在达到相当高级的状态时才将其移动到公共分支的原因之一。
随着主线(或一组更改所基于的其他树)的推进,很想与该树合并以保持领先地位。对于私有分支,rebase 可以是跟上另一棵树的简单方法,但是一旦将树导出到世界,rebase 就不是一个选项了。一旦发生这种情况,必须进行完全合并。偶尔合并很有意义,但过于频繁的合并会不必要地使历史混乱。在这种情况下,建议的技术是不频繁地合并,并且通常仅在特定的发布点(例如主线 -rc 版本)合并。如果您对特定更改感到紧张,您始终可以在私有分支中执行测试合并。git “rerere” 工具在这种情况下很有用;它会记住如何解决合并冲突,这样您就不必做两次相同的工作。
关于像 git 这样的工具,最大的反复抱怨之一是:补丁从一个存储库到另一个存储库的大量移动使得容易滑入不谨慎的更改,这些更改在审查雷达之下进入主线。内核开发人员看到这种情况发生时往往会感到不高兴;发布带有未经审查或与主题无关的补丁的 git 树会影响您将来获取树的能力。引用 Linus
You can send me patches, but for me to pull a git patch from you, I
need to know that you know what you're doing, and I need to be able
to trust things *without* then having to go and check every
individual change by hand.
(https://lwn.net/Articles/224135/)。
为避免这种情况,请确保给定分支中的所有补丁都紧密地贴合相关主题;“驱动程序修复”分支不应更改核心内存管理代码。而且,最重要的是,不要使用 git 树来绕过审查过程。定期向相关列表发布树的摘要,并在合适的时候,请求将该树包含在 linux-next 中。
如果其他人开始发送补丁以包含到您的树中,请不要忘记审查它们。还要确保您维护正确的作者信息;git “am” 工具在这方面尽了最大努力,但如果补丁是通过第三方转发给您的,您可能需要在补丁中添加 “From:” 行。
请求拉取时,请务必提供所有相关信息:您的树在哪里、要拉取哪个分支以及拉取会导致哪些更改。git request-pull 命令在这方面很有用;它将按照其他开发人员的期望格式化请求,并且还将检查以确保您已将这些更改推送到公共服务器。
7.2. 审查补丁¶
一些读者肯定会反对将本节放在“高级主题”中,理由是即使是初学者内核开发人员也应该审查补丁。当然,在内核环境中学习如何编程的最好方法是查看其他人发布的代码。此外,审阅者总是供不应求;通过查看代码,您可以为整个过程做出重大贡献。
审查代码可能是一项令人生畏的前景,尤其是对于可能对公开质疑那些经验更丰富的人发布的代码感到紧张的新内核开发人员而言。但是,即使是最有经验的开发人员编写的代码也可以改进。对于审阅者(所有审阅者)来说,最好的建议可能是:将审阅评论表述为问题而不是批评。“此路径中的锁是如何释放的?”的提问总是比“此处的锁定是错误的”的陈述效果更好。
在发生分歧时有用的另一种技巧是请其他人加入。如果讨论在几次交流后陷入僵局,请征求其他审阅者或维护者的意见。通常,同意审阅者意见的人会保持沉默,除非被要求。多个人的意见的权重呈指数级增加。
不同的开发人员会从不同的角度审查代码。有些人主要关注编码风格以及代码行是否具有尾随空格。另一些人将主要关注补丁所实现的整体更改对于内核是否有利。还有一些人会检查是否有问题的锁定、过度堆栈使用、可能的安全问题、在其他地方发现的代码重复、足够的文档、对性能的不利影响、用户空间 ABI 更改等。所有类型的审查,如果它们导致更好的代码进入内核,都值得欢迎和有价值。
没有严格的要求使用特定的标记,例如 Reviewed-by
。实际上,即使提供了标记,纯英语的评论也更具信息性和鼓励性,例如“我查看了此提交的 A、B 和 C 方面,它对我来说看起来不错。”显然需要某种形式的评论消息或回复,否则维护者将根本不知道审阅者是否看过补丁!
最后但并非最不重要的一点是,补丁审查可能会成为一个负面过程,重点是指出现的问题。请时不时地表示一下赞扬,特别是对于新手!