3. 早期规划

在考虑 Linux 内核开发项目时,人们往往会忍不住直接跳进去开始编写代码。不过,与任何重大项目一样,成功的大部分基础工作最好在编写第一行代码之前就铺设好。花一些时间进行早期规划和沟通,以后可以节省更多的时间。

3.1. 明确问题

就像任何工程项目一样,成功的内核增强始于对要解决的问题的清晰描述。在某些情况下,这一步很简单:例如,当需要特定硬件的驱动程序时。然而,在另一些情况下,人们很容易将真实问题与提出的解决方案混淆,这可能会导致困难。

考虑这样一个例子:几年前,从事 Linux 音频开发的开发者寻求一种方法来运行应用程序,以避免由于系统中过高的延迟而导致的音频中断或其他失真。他们得出的解决方案是一个内核模块,旨在挂载到 Linux 安全模块(LSM)框架中;该模块可以配置为赋予特定应用程序访问实时调度器的权限。这个模块被实现并发送到了 linux-kernel 邮件列表,在那里它立即遇到了问题。

对于音频开发者来说,这个安全模块足以解决他们当下的问题。然而,对于更广泛的内核社区而言,这被视为对 LSM 框架的滥用(该框架本意并非赋予进程原本不具备的特权),并且对系统稳定性构成了风险。他们更倾向的解决方案是:短期内通过 rlimit 机制访问实时调度,长期则持续进行降低延迟的工作。

然而,音频社区无法跳出他们所实现的特定解决方案;他们不愿意接受替代方案。由此产生的意见分歧让这些开发者对整个内核开发过程感到幻灭;其中一人回到音频邮件列表并发布了这样一段话:

有许多非常优秀的 Linux 内核开发者,但他们往往被一大群傲慢的蠢货的声音所淹没。试图与这些人沟通用户需求纯属浪费时间。他们太“聪明”了,根本不会听取凡夫俗子的意见。

(https://lwn.net/Articles/131776/).

现实情况并非如此;内核开发者远比关心某个特定模块更关心系统稳定性、长期维护以及为该问题找到正确的解决方案。这个故事给我们的教训是:要专注于问题本身——而不是某个特定的方案——在投入大量代码编写之前,先与开发社区进行讨论。

因此,在考虑内核开发项目时,应当先回答几个简短的问题

  • 需要解决的问题究竟是什么?

  • 受此问题影响的用户有哪些?该解决方案应解决哪些用例?

  • 目前内核在解决该问题方面有哪些不足?

只有在明确这些之后,开始考虑可能的解决方案才有意义。

3.2. 早期讨论

在规划内核开发项目时,在开始实施之前与社区进行讨论是非常有意义的。早期沟通可以通过多种方式节省时间和麻烦

  • 很可能内核已经用你尚未理解的方式解决该问题了。Linux 内核非常庞大,拥有许多并非一眼就能看出来的特性和功能。并非所有的内核功能都像人们希望的那样文档齐全,因此很容易遗漏某些东西。本文作者就曾见过有人发布了一个完整的驱动程序,而该驱动程序与一个新作者并不知晓的现有驱动程序完全重复。重复发明已有轮子的代码不仅是浪费;而且也不会被合并到主线内核中。

  • 拟议的解决方案中可能包含一些无法为主线合并接受的元素。最好在编写代码之前就发现这类问题。

  • 其他开发者完全有可能也考虑过这个问题;他们可能会有更好解决方案的想法,并且可能愿意协助创建该解决方案。

与内核开发社区打交道的多年经验教会了我们一个深刻的教训:在闭门造车的情况下设计和开发的内核代码,必然会暴露出一些问题,而这些问题只有在代码发布到社区时才会显现出来。有时这些问题非常严重,需要花费数月甚至数年的努力才能使代码达到内核社区的标准。一些例子包括

  • Devicescape 网络栈是为单处理器系统设计和实现的。在使其适应多处理器系统之前,它无法合并到主线中。将锁机制等改造到代码中是一项艰巨的任务;因此,该代码(现称为 mac80211)的合并被推迟了一年多。

  • Reiser4 文件系统包含许多功能,核心内核开发者认为这些功能本应在虚拟文件系统层中实现。它还包含一些特性,如果不将系统暴露给由用户引起的死锁风险,就很难实现。这些问题直到后期才被暴露出来——并且拒绝解决其中一些问题——这导致 Reiser4 一直未能进入主线内核。

  • AppArmor 安全模块以被认为是不安全和不可靠的方式使用了内部虚拟文件系统数据结构。这一担忧(以及其他因素)使 AppArmor 多年来一直被排除在主线之外。

在上述每种情况下,如果能与内核开发者进行一些早期沟通,就可以避免大量的痛苦和额外工作。

3.3. 应该与谁沟通?

当开发者决定将其计划公开时,接下来的问题将是:我们从哪里开始?答案是找到正确的邮件列表和合适的维护者。对于邮件列表,最好的方法是在 MAINTAINERS 文件中寻找相关发布位置。如果有合适的子系统邮件列表,向该列表发帖通常比发到 linux-kernel 更好;你更有可能接触到具备相关子系统专业知识的开发者,并且环境可能更具支持性。

寻找维护者可能会更难一些。同样,MAINTAINERS 文件是起点。不过,该文件往往不总是最新的,而且并非所有子系统都在其中有代表。MAINTAINERS 文件中列出的人可能实际上并不是当前真正在履行该职责的人。因此,当对联系谁存有疑问时,一个有用的技巧是使用 git(特别是 “git log”)来查看谁在感兴趣的子系统中目前很活跃。看看是谁在编写补丁,以及是否有谁在这些补丁上附加了 Signed-off-by 行。这些人将是协助新开发项目的最佳人选。

寻找合适维护者的任务有时极具挑战性,以至于内核开发者专门添加了一个脚本来简化这一过程

.../scripts/get_maintainer.pl

当给定 “-f” 选项时,该脚本将返回给定文件或目录的当前维护者。如果在命令行中传入一个补丁,它将列出应该接收该补丁副本的维护者。这是获取你的补丁的抄送(Cc)人员列表的首选方法(与 “-f” 选项不同)。有许多选项规定了 get_maintainer.pl 寻找维护者的力度;请谨慎使用更激进的选项,因为你最终可能会把对你修改的代码根本不感兴趣的开发者包含进来。

如果所有其他方法都失败了,与 Andrew Morton 沟通可能是追踪特定代码维护者的有效方法。

3.4. 何时发布?

如果可能的话,在早期阶段发布你的计划只有好处。描述正在解决的问题以及关于如何进行实现的任何既定计划。你所提供的任何信息都可以帮助开发社区对该项目提供有用的意见。

在这个阶段可能发生的令人沮丧的事情不是敌对的反应,而是几乎没有甚至完全没有反应。一个悲哀的事实是 (1) 内核开发者通常都很忙,(2) 从不缺那些满怀宏伟计划却没有什么代码(甚至连代码前景都没有)来支撑的人,以及 (3) 没有人有义务去审查或评论别人发布的想法。除此之外,高层设计往往隐藏着一些问题,只有当有人真正尝试实现这些设计时才会暴露出来;正因如此,内核开发者更愿意看到代码。

如果一份征求意见的帖子几乎没有收获什么评论,切勿因此认为大家对该项目不感兴趣。不幸的是,你也不能假设你的想法没有任何问题。在这种情况下,最好的做法是继续推进,并在推进过程中随时向社区通报情况。

3.5. 获取官方认可

如果你的工作是在企业环境中进行的——大多数 Linux 内核工作都是如此——那么在将你公司的计划或代码发布到公共邮件列表之前,显然必须获得具有适当职权的经理的许可。发布未经批准以兼容 GPL 的许可证发布的代码可能会带来严重问题;公司的管理层和法律人员越早就能对发布内核开发项目达成一致,所有相关人员就会越受益。

此时,一些读者可能会认为,他们的内核工作旨在支持一个尚未官方承认存在的产品。在公共邮件列表上透露其雇主的计划可能不是一个可行的选择。在这种情况下,值得考虑的是,这种保密是否有必要;通常根本没有必要将开发计划秘而不宣。

话虽如此,也确实存在某些情况下,公司在开发过程的早期阶段合法地不能披露其计划。拥有经验丰富的内核开发者的公司可能会选择以开环方式进行,前提是他们能够避免以后出现严重的集成问题。对于没有这种内部专业知识的公司来说,最好的选择通常是聘请外部开发者在保密协议下审查这些计划。Linux 基金会运营着一个旨在帮助处理此类情况的 NDA 计划;更多信息可以在以下网址找到

这种形式的审查通常足以避免以后出现严重问题,同时又无需公开披露该项目。