0001 .. include:: ../disclaimer-zh_CN.rst
0002
0003 :Original: :ref:`Documentation/process/2.Process.rst <development_process>`
0004
0005 :Translator:
0006
0007 时奎亮 Alex Shi <alex.shi@linux.alibaba.com>
0008
0009 :校译:
0010
0011 吴想成 Wu XiangCheng <bobwxc@email.cn>
0012
0013 .. _cn_development_process:
0014
0015 开发流程如何进行
0016 ================
0017
0018 90年代早期的Linux内核开发是一件相当松散的事情,涉及的用户和开发人员相对较少。
0019 由于拥有数以百万计的用户群,且每年有大约2000名开发人员参与进来,内核因此必须
0020 发展出许多既定流程来保证开发的顺利进行。要参与到流程中来,需要对此流程的进行
0021 方式有一个扎实的理解。
0022
0023 总览
0024 ----
0025
0026 内核开发人员使用一个松散的基于时间的发布过程,每两到三个月发布一次新的主要
0027 内核版本。最近的发布历史记录如下:
0028
0029 ====== =================
0030 5.0 2019年3月3日
0031 5.1 2019年5月5日
0032 5.2 2019年7月7日
0033 5.3 2019年9月15日
0034 5.4 2019年11月24日
0035 5.5 2020年1月6日
0036 ====== =================
0037
0038 每个5.x版本都是一个主要的内核版本,具有新特性、内部API更改等等。一个典型的5.x
0039 版本包含大约13000个变更集,变更了几十万行代码。因此,5.x是Linux内核开发的前
0040 沿;内核使用滚动开发模型,不断集成重大变化。
0041
0042 对于每个版本的补丁合并,遵循一个相对简单的规则。在每个开发周期的开头,“合并
0043 窗口”被打开。这时,被认为足够稳定(并且被开发社区接受)的代码被合并到主线内
0044 核中。在这段时间内,新开发周期的大部分变更(以及所有主要变更)将以接近每天
0045 1000次变更(“补丁”或“变更集”)的速度合并。
0046
0047 (顺便说一句,值得注意的是,合并窗口期间集成的更改并不是凭空产生的;它们是经
0048 提前收集、测试和分级的。稍后将详细描述该过程的工作方式。)
0049
0050 合并窗口持续大约两周。在这段时间结束时,Linus Torvalds将声明窗口已关闭,并
0051 释放第一个“rc”内核。例如,对于目标为5.6的内核,在合并窗口结束时发生的释放
0052 将被称为5.6-rc1。-rc1 版本是一个信号,表示合并新特性的时间已经过去,稳定下一
0053 个内核的时间已经到来。
0054
0055 在接下来的6到10周内,只有修复问题的补丁才应该提交给主线。有时会允许更大的
0056 更改,但这种情况很少发生;试图在合并窗口外合并新功能的开发人员往往受不到
0057 友好的接待。一般来说,如果您错过了给定特性的合并窗口,最好的做法是等待下一
0058 个开发周期。(偶尔会对未支持硬件的驱动程序进行例外;如果它们不改变已有代码,
0059 则不会导致回归,应该可以随时被安全地加入)。
0060
0061 随着修复程序进入主线,补丁速度将随着时间的推移而变慢。Linus大约每周发布一次
0062 新的-rc内核;在内核被认为足够稳定并最终发布前,一般会达到-rc6到-rc9之间。
0063 然后,整个过程又重新开始了。
0064
0065 例如,这里是5.4的开发周期进行情况(2019年):
0066
0067 ============== ==============================
0068 九月 15 5.3 稳定版发布
0069 九月 30 5.4-rc1 合并窗口关闭
0070 十月 6 5.4-rc2
0071 十月 13 5.4-rc3
0072 十月 20 5.4-rc4
0073 十月 27 5.4-rc5
0074 十一月 3 5.4-rc6
0075 十一月 10 5.4-rc7
0076 十一月 17 5.4-rc8
0077 十一月 24 5.4 稳定版发布
0078 ============== ==============================
0079
0080 开发人员如何决定何时结束开发周期并创建稳定版本?最重要的指标是以前版本的
0081 回归列表。不欢迎出现任何错误,但是那些破坏了以前能工作的系统的错误被认为是
0082 特别严重的。因此,导致回归的补丁是不受欢迎的,很可能在稳定期内删除。
0083
0084 开发人员的目标是在稳定发布之前修复所有已知的回归。在现实世界中,这种完美是
0085 很难实现的;在这种规模的项目中,变数太多了。需要说明的是,延迟最终版本只会
0086 使问题变得更糟;等待下一个合并窗口的更改将变多,导致下次出现更多的回归错误。
0087 因此,大多数5.x内核都有一些已知的回归错误,不过,希望没有一个是严重的。
0088
0089 一旦一个稳定的版本发布,它的持续维护工作就被移交给“稳定团队”,目前由
0090 Greg Kroah-Hartman领导。稳定团队将使用5.x.y编号方案不定期地发布稳定版本的
0091 更新。要合入更新版本,补丁必须(1)修复一个重要的缺陷,且(2)已经合并到
0092 下一个开发版本主线中。内核通常会在其初始版本后的一个以上的开发周期内收到
0093 稳定版更新。例如,5.2内核的历史如下(2019年):
0094
0095 ============== ===============================
0096 七月 7 5.2 稳定版发布
0097 七月 13 5.2.1
0098 七月 21 5.2.2
0099 七月 26 5.2.3
0100 七月 28 5.2.4
0101 七月 31 5.2.5
0102 ... ...
0103 十月 11 5.2.21
0104 ============== ===============================
0105
0106 5.2.21是5.2版本的最终稳定更新。
0107
0108 有些内核被指定为“长期”内核;它们将得到更长时间的支持。在本文中,当前的长期
0109 内核及其维护者是:
0110
0111 ====== ================================ ================
0112 3.16 Ben Hutchings (长期稳定内核)
0113 4.4 Greg Kroah-Hartman & Sasha Levin (长期稳定内核)
0114 4.9 Greg Kroah-Hartman & Sasha Levin
0115 4.14 Greg Kroah-Hartman & Sasha Levin
0116 4.19 Greg Kroah-Hartman & Sasha Levin
0117 5.4 Greg Kroah-Hartman & Sasha Levin
0118 ====== ================================ ================
0119
0120 长期支持内核的选择纯粹是维护人员是否有需求和时间来维护该版本的问题。
0121 目前还没有为即将发布的任何特定版本提供长期支持的已知计划。
0122
0123 补丁的生命周期
0124 --------------
0125
0126 补丁不会直接从开发人员的键盘进入主线内核。相反,有一个稍微复杂(如果有些非
0127 正式)的过程,旨在确保对每个补丁进行质量审查,并确保每个补丁实现了一个在主线
0128 中需要的更改。对于小的修复,这个过程可能会很快完成,,而对于较大或有争议的
0129 变更,可能会持续数年。许多开发人员的沮丧来自于对这个过程缺乏理解或者试图绕过它。
0130
0131 为了减少这种挫败,本文将描述补丁如何进入内核。下面的介绍以一种较为理想化的
0132 方式描述了这个过程。更详细的过程将在后面的章节中介绍。
0133
0134 补丁通常要经历以下阶段:
0135
0136 - 设计。这就是补丁的真正需求——以及满足这些需求的方式——所在。设计工作通常
0137 是在不涉及社区的情况下完成的,但是如果可能的话,最好是在公开的情况下完成
0138 这项工作;这样可以节省很多稍后再重新设计的时间。
0139
0140 - 早期评审。补丁被发布到相关的邮件列表中,列表中的开发人员会回复他们可能有
0141 的任何评论。如果一切顺利的话,这个过程应该会发现补丁的任何主要问题。
0142
0143 - 更广泛的评审。当补丁接近准备好纳入主线时,它应该被相关的子系统维护人员
0144 接受——尽管这种接受并不能保证补丁会一直延伸到主线。补丁将出现在维护人员的
0145 子系统树中,并进入 -next 树(如下所述)。当流程进行时,此步骤将会对补丁
0146 进行更广泛的审查,并发现由于将此补丁与其他人所做的工作合并而导致的任何
0147 问题。
0148
0149 - 请注意,大多数维护人员也有日常工作,因此合并补丁可能不是他们的最优先工作。
0150 如果您的补丁得到了需要更改的反馈,那么您应该进行这些更改,或者解释为何
0151 不应该进行这些更改。如果您的补丁没有评审意见,也没有被其相应的子系统或
0152 驱动程序维护者接受,那么您应该坚持不懈地将补丁更新到当前内核使其可被正常
0153 应用,并不断地发送它以供审查和合并。
0154
0155 - 合并到主线。最终,一个成功的补丁将被合并到由LinusTorvalds管理的主线存储库
0156 中。此时可能会出现更多的评论和/或问题;对开发人员来说应对这些问题并解决
0157 出现的任何问题仍很重要。
0158
0159 - 稳定版发布。大量用户可能受此补丁影响,因此可能再次出现新的问题。
0160
0161 - 长期维护。虽然开发人员在合并代码后可能会忘记代码,但这种行为往往会给开发
0162 社区留下不良印象。合并代码消除了一些维护负担,因为其他人将修复由API更改
0163 引起的问题。但是,如果代码要长期保持可用,原始开发人员应该继续为代码负责。
0164
0165 内核开发人员(或他们的雇主)犯的最大错误之一是试图将流程简化为一个“合并到
0166 主线”步骤。这种方法总是会让所有相关人员感到沮丧。
0167
0168 补丁如何进入内核
0169 ----------------
0170
0171 只有一个人可以将补丁合并到主线内核存储库中:Linus Torvalds。但是,在进入
0172 2.6.38内核的9500多个补丁中,只有112个(大约1.3%)是由Linus自己直接选择的。
0173 内核项目已经发展到一个没有一个开发人员可以在没有支持的情况下检查和选择每个
0174 补丁的规模。内核开发人员处理这种增长的方式是使用围绕信任链构建的助理系统。
0175
0176 内核代码库在逻辑上被分解为一组子系统:网络、特定体系结构支持、内存管理、视
0177 频设备等。大多数子系统都有一个指定的维护人员,其总体负责该子系统中的代码。
0178 这些子系统维护者(松散地)是他们所管理的内核部分的“守门员”;他们(通常)
0179 会接受一个补丁以包含到主线内核中。
0180
0181 子系统维护人员每个人都管理着自己版本的内核源代码树,通常(并非总是)使用Git。
0182 Git等工具(以及Quilt或Mercurial等相关工具)允许维护人员跟踪补丁列表,包括作者
0183 信息和其他元数据。在任何给定的时间,维护人员都可以确定他或她的存储库中的哪
0184 些补丁在主线中找不到。
0185
0186 当合并窗口打开时,顶级维护人员将要求Linus从存储库中“拉出”他们为合并选择
0187 的补丁。如果Linus同意,补丁流将流向他的存储库,成为主线内核的一部分。
0188 Linus对拉取中接收到的特定补丁的关注程度各不相同。很明显,有时他看起来很
0189 关注。但是一般来说,Linus相信子系统维护人员不会向上游发送坏补丁。
0190
0191 子系统维护人员反过来也可以从其他维护人员那里获取补丁。例如,网络树是由首先
0192 在专用于网络设备驱动程序、无线网络等的树中积累的补丁构建的。此存储链可以
0193 任意长,但很少超过两个或三个链接。由于链中的每个维护者都信任那些管理较低
0194 级别树的维护者,所以这个过程称为“信任链”。
0195
0196 显然,在这样的系统中,获取内核补丁取决于找到正确的维护者。直接向Linus发送
0197 补丁通常不是正确的方法。
0198
0199 Next 树
0200 -------
0201
0202 子系统树链引导补丁流到内核,但它也提出了一个有趣的问题:如果有人想查看为
0203 下一个合并窗口准备的所有补丁怎么办?开发人员将感兴趣的是,还有什么其他的
0204 更改有待解决,以了解是否存在需要担心的冲突;例如,更改核心内核函数原型的
0205 修补程序将与使用该函数旧形式的任何其他修补程序冲突。审查人员和测试人员希望
0206 在所有这些变更到达主线内核之前,能够访问它们的集成形式的变更。您可以从所有
0207 相关的子系统树中提取更改,但这将是一项复杂且容易出错的工作。
0208
0209 解决方案以-next树的形式出现,在这里子系统树被收集以供测试和审查。这些树中
0210 由Andrew Morton维护的较老的一个,被称为“-mm”(用于内存管理,创建时为此)。
0211 -mm 树集成了一长串子系统树中的补丁;它还包含一些旨在帮助调试的补丁。
0212
0213 除此之外,-mm 还包含大量由Andrew直接选择的补丁。这些补丁可能已经发布在邮件
0214 列表上,或者它们可能应用于内核中未指定子系统树的部分。同时,-mm 作为最后
0215 手段的子系统树;如果没有其他明显的路径可以让补丁进入主线,那么它很可能最
0216 终选择-mm 树。累积在-mm 中的各种补丁最终将被转发到适当的子系统树,或者直接
0217 发送到Linus。在典型的开发周期中,大约5-10%的补丁通过-mm 进入主线。
0218
0219 当前-mm 补丁可在“mmotm”(-mm of the moment)目录中找到:
0220
0221 https://www.ozlabs.org/~akpm/mmotm/
0222
0223 然而,使用MMOTM树可能会十分令人头疼;它甚至可能无法编译。
0224
0225 下一个周期补丁合并的主要树是linux-next,由Stephen Rothwell 维护。根据设计
0226 linux-next 是下一个合并窗口关闭后主线的快照。linux-next树在Linux-kernel 和
0227 Linux-next 邮件列表中发布,可从以下位置下载:
0228
0229 https://www.kernel.org/pub/linux/kernel/next/
0230
0231 Linux-next 已经成为内核开发过程中不可或缺的一部分;在一个给定的合并窗口中合并
0232 的所有补丁都应该在合并窗口打开之前的一段时间内找到进入Linux-next 的方法。
0233
0234 Staging 树
0235 ----------
0236
0237 内核源代码树包含drivers/staging/目录,其中有许多驱动程序或文件系统的子目录
0238 正在被添加到内核树中。它们在仍然需要更多的修正的时候可以保留在driver/staging/
0239 目录中;一旦完成,就可以将它们移到内核中。这是一种跟踪不符合Linux内核编码或
0240 质量标准的驱动程序的方法,人们可能希望使用它们并跟踪开发。
0241
0242 Greg Kroah Hartman 目前负责维护staging 树。仍需要修正的驱动程序将发送给他,
0243 每个驱动程序在drivers/staging/中都有自己的子目录。除了驱动程序源文件之外,
0244 目录中还应该有一个TODO文件。TODO文件列出了驱动程序需要接受的暂停的工作,
0245 以及驱动程序的任何补丁都应该抄送的人员列表。当前的规则要求,staging的驱动
0246 程序必须至少正确编译。
0247
0248 Staging 是一种让新的驱动程序进入主线的相对容易的方法,它们会幸运地引起其他
0249 开发人员的注意,并迅速改进。然而,进入staging并不是故事的结尾;staging中
0250 没有看到常规进展的代码最终将被删除。经销商也倾向于相对不愿意使用staging驱动
0251 程序。因此,在成为一个合适的主线驱动的路上,staging 仅是一个中转站。
0252
0253 工具
0254 ----
0255
0256 从上面的文本可以看出,内核开发过程在很大程度上依赖于在不同方向上聚集补丁的
0257 能力。如果没有适当强大的工具,整个系统将无法在任何地方正常工作。关于如何使用
0258 这些工具的教程远远超出了本文档的范围,但还是用一点篇幅介绍一些关键点。
0259
0260 到目前为止,内核社区使用的主要源代码管理系统是git。Git是在自由软件社区中开发
0261 的许多分布式版本控制系统之一。它非常适合内核开发,因为它在处理大型存储库和
0262 大量补丁时性能非常好。它也以难以学习和使用而著称,尽管随着时间的推移它变得
0263 更好了。对于内核开发人员来说,对Git的某种熟悉几乎是一种要求;即使他们不将它
0264 用于自己的工作,他们也需要Git来跟上其他开发人员(以及主线)正在做的事情。
0265
0266 现在几乎所有的Linux发行版都打包了Git。Git主页位于:
0267
0268 https://git-scm.com/
0269
0270 此页面包含了文档和教程的链接。
0271
0272 在不使用git的内核开发人员中,最流行的选择几乎肯定是Mercurial:
0273
0274 http://www.seleric.com/mercurial/
0275
0276 Mercurial与Git共享许多特性,但它提供了一个界面,许多人觉得它更易于使用。
0277
0278 另一个值得了解的工具是Quilt:
0279
0280 https://savannah.nongnu.org/projects/quilt
0281
0282 Quilt 是一个补丁管理系统,而不是源代码管理系统。它不会随着时间的推移跟踪历史;
0283 相反,它面向根据不断发展的代码库跟踪一组特定的更改。一些主要的子系统维护人员
0284 使用Quilt来管理打算向上游移动的补丁。对于某些树的管理(例如-mm),quilt 是
0285 最好的工具。
0286
0287 邮件列表
0288 --------
0289
0290 大量的Linux内核开发工作是通过邮件列表完成的。如果不加入至少一个某个列表,
0291 就很难成为社区中的一个“全功能”成员。但是,Linux邮件列表对开发人员来说也是
0292 一个潜在的危险,他们可能会被一堆电子邮件淹没、违反Linux列表上使用的约定,
0293 或者两者兼而有之。
0294
0295 大多数内核邮件列表都在vger.kernel.org上运行;主列表位于:
0296
0297 http://vger.kernel.org/vger-lists.html
0298
0299 不过,也有一些列表托管在别处;其中一些列表位于
0300 redhat.com/mailman/listinfo。
0301
0302 当然,内核开发的核心邮件列表是linux-kernel。这个列表是一个令人生畏的地方:
0303 每天的信息量可以达到500条,噪音很高,谈话技术性很强,且参与者并不总是表现出
0304 高度的礼貌。但是,没有其他地方可以让内核开发社区作为一个整体聚集在一起;
0305 不使用此列表的开发人员将错过重要信息。
0306
0307 以下一些提示可以帮助在linux-kernel生存:
0308
0309 - 将邮件转移到单独的文件夹,而不是主邮箱文件夹。我们必须能够持续地忽略洪流。
0310
0311 - 不要试图跟上每一次谈话——没人会这样。重要的是要筛选感兴趣的主题(但请注意
0312 长时间的对话可能会偏离原来的主题,尽管未改变电子邮件的主题)和参与的人。
0313
0314 - 不要回复挑事的人。如果有人试图激起愤怒,请忽略他们。
0315
0316 - 当回复Linux内核电子邮件(或其他列表上的电子邮件)时,请为所有相关人员保留
0317 Cc: 抄送头。如果没有确实的理由(如明确的请求),则不应删除收件人。一定要
0318 确保你要回复的人在抄送列表中。这个惯例也使你不必在回复邮件时明确要求被抄送。
0319
0320 - 在提出问题之前,搜索列表存档(和整个网络)。有些开发人员可能会对那些显然
0321 没有完成家庭作业的人感到不耐烦。
0322
0323 - 避免顶部回复(把你的答案放在你要回复的引文上面的做法)。这会让你的回答更难
0324 理解,印象也很差。
0325
0326 - 在正确的邮件列表发问。linux-kernel 可能是通用的讨论场所,但它不是寻找所有
0327 子系统开发人员的最佳场所。
0328
0329 最后一点——找到正确的邮件列表——是开发人员常出错的地方。在linux-kernel上
0330 提出与网络相关的问题的人几乎肯定会收到一个礼貌的建议,转到netdev列表上提出,
0331 因为这是大多数网络开发人员经常出现的列表。还有其他列表可用于scsi、video4linux、
0332 ide、filesystem等子系统。查找邮件列表的最佳位置是与内核源代码一起打包的
0333 MAINTAINERS文件。
0334
0335 开始内核开发
0336 ------------
0337
0338 关于如何开始内核开发过程的问题很常见——个人和公司皆然。同样常见的是失误,这
0339 使得关系的开始比本应的更困难。
0340
0341 公司通常希望聘请知名的开发人员来启动开发团队。实际上,这是一种有效的技术。
0342 但它也往往是昂贵的,而且对增加有经验的内核开发人员的数量没有多大帮助。考
0343 虑到时间投入,可以让内部开发人员加快Linux内核的开发速度。利用这段时间可以
0344 让雇主拥有一批既了解内核又了解公司的开发人员,还可以帮助培训其他人。从中期
0345 来看,这通常是更有利可图的方法。
0346
0347 可以理解的是,单个开发人员往往对起步感到茫然。从一个大型项目开始可能会很
0348 吓人;人们往往想先用一些较小的东西来试试水。由此,一些开发人员开始创建修补
0349 拼写错误或轻微编码风格问题的补丁。不幸的是,这样的补丁会产生一定程度的噪音,
0350 这会分散整个开发社区的注意力,因此,它们越来越被人不看重。希望向社区介绍
0351 自己的新开发人员将无法通过这些方式获得他们期待的反响。
0352
0353 Andrew Morton 为有抱负的内核开发人员提供了如下建议
0354
0355 ::
0356
0357 所有内核开发者的第一个项目肯定应该是“确保内核在您可以操作的所有
0358 机器上始终完美运行”。通常的方法是和其他人一起解决问题(这可能需
0359 要坚持!),但就是如此——这是内核开发的一部分。
0360
0361 (http://lwn.net/articles/283982/)
0362
0363 在没有明显问题需要解决的情况下,通常建议开发人员查看当前的回归和开放缺陷
0364 列表。从来都不缺少需要解决的问题;通过解决这些问题,开发人员将从该过程获得
0365 经验,同时与开发社区的其他成员建立相互尊重。