diff options
Diffstat (limited to 'Documentation/translations/zh_CN/process')
25 files changed, 5573 insertions, 0 deletions
diff --git a/Documentation/translations/zh_CN/process/1.Intro.rst b/Documentation/translations/zh_CN/process/1.Intro.rst new file mode 100644 index 000000000000..10a15f3dc282 --- /dev/null +++ b/Documentation/translations/zh_CN/process/1.Intro.rst @@ -0,0 +1,186 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_process_intro: + +介绍 +==== + +执行摘要 +-------- + +本节的其余部分涵盖了内核开发过程的范围,以及开发人员及其雇主在这方面可能遇 +到的各种挫折。内核代码应该合并到正式的(“主线”)内核中有很多原因,包括对用 +户的自动可用性、多种形式的社区支持以及影响内核开发方向的能力。提供给Linux +内核的代码必须在与GPL兼容的许可证下可用。 + +:ref:`cn_development_process` 介绍了开发过程、内核发布周期和合并窗口的机制。 +涵盖了补丁开发、审查和合并周期中的各个阶段。有一些关于工具和邮件列表的讨论。 +鼓励希望开始内核开发的开发人员作为初始练习跟踪并修复bug。 + + +:ref:`cn_development_early_stage` 包括早期项目规划,重点是尽快让开发社区参与 + +:ref:`cn_development_coding` 是关于编码过程的;讨论了其他开发人员遇到的几个 +陷阱。对补丁的一些要求已经涵盖,并且介绍了一些工具,这些工具有助于确保内核 +补丁是正确的。 + +:ref:`cn_development_posting` 讨论发布补丁以供评审的过程。为了让开发社区 +认真对待,补丁必须正确格式化和描述,并且必须发送到正确的地方。遵循本节中的 +建议有助于确保为您的工作提供最好的接纳。 + +:ref:`cn_development_followthrough` 介绍了发布补丁之后发生的事情;该工作 +在这一点上还远远没有完成。与审阅者一起工作是开发过程中的一个重要部分;本节 +提供了一些关于如何在这个重要阶段避免问题的提示。当补丁被合并到主线中时, +开发人员要注意不要假定任务已经完成。 + +:ref:`cn_development_advancedtopics` 介绍了两个“高级”主题: +使用Git管理补丁和查看其他人发布的补丁。 + +:ref:`cn_development_conclusion` 总结了有关内核开发的更多信息,附带有带有 +指向资源的链接. + +这个文件是关于什么的 +-------------------- + +Linux内核有超过800万行代码,每个版本的贡献者超过1000人,是现存最大、最活跃 +的免费软件项目之一。从1991年开始,这个内核已经发展成为一个最好的操作系统 +组件,运行在袖珍数字音乐播放器、台式PC、现存最大的超级计算机以及所有类型的 +系统上。它是一种适用于几乎任何情况的健壮、高效和可扩展的解决方案。 + +随着Linux的发展,希望参与其开发的开发人员(和公司)的数量也在增加。硬件供应商 +希望确保Linux能够很好地支持他们的产品,使这些产品对Linux用户具有吸引力。嵌入 +式系统供应商使用Linux作为集成产品的组件,希望Linux能够尽可能地胜任手头的任务。 +分销商和其他基于Linux的软件供应商对Linux内核的功能、性能和可靠性有着明确的 +兴趣。最终用户也常常希望修改Linux,使之更好地满足他们的需求。 + +Linux最引人注目的特性之一是这些开发人员可以访问它;任何具备必要技能的人都可以 +改进Linux并影响其开发方向。专有产品不能提供这种开放性,这是自由软件的一个特点。 +但是,如果有什么不同的话,内核比大多数其他自由软件项目更开放。一个典型的三个月 +内核开发周期可以涉及1000多个开发人员,他们为100多个不同的公司 +(或者根本没有公司)工作。 + +与内核开发社区合作并不是特别困难。但是,尽管如此,许多潜在的贡献者在尝试做 +内核工作时遇到了困难。内核社区已经发展了自己独特的操作方式,使其能够在每天 +都要更改数千行代码的环境中顺利运行(并生成高质量的产品)。因此,Linux内核开发 +过程与专有的开发方法有很大的不同也就不足为奇了。 + +对于新开发人员来说,内核的开发过程可能会让人感到奇怪和恐惧,但这个背后有充分的 +理由和坚实的经验。一个不了解内核社区的方式的开发人员(或者更糟的是,他们试图 +抛弃或规避内核社区的方式)会有一个令人沮丧的体验。开发社区, 在帮助那些试图学习 +的人的同时,没有时间帮助那些不愿意倾听或不关心开发过程的人。 + +希望阅读本文的人能够避免这种令人沮丧的经历。这里有很多材料,但阅读时所做的 +努力会在短时间内得到回报。开发社区总是需要能让内核变更好的开发人员;下面的 +文本应该帮助您或为您工作的人员加入我们的社区。 + +致谢 +---- + +本文件由Jonathan Corbet撰写,corbet@lwn.net。以下人员的建议使之更为完善: +Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap, +Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson, +Andrew Morton, Andrew Price, Tsugikazu Shibata, 和 Jochen Voß. + +这项工作得到了Linux基金会的支持,特别感谢Amanda McPherson,他看到了这项工作 +的价值并把它变成现实。 + +代码进入主线的重要性 +-------------------- + +有些公司和开发人员偶尔会想,为什么他们要费心学习如何与内核社区合作,并将代码 +放入主线内核(“主线”是由Linus Torvalds维护的内核,Linux发行商将其用作基础)。 +在短期内,贡献代码看起来像是一种可以避免的开销;仅仅将代码分开并直接支持用户 +似乎更容易。事实上,保持代码独立(“树外”)是在经济上是错误的。 + +作为说明树外代码成本的一种方法,下面是内核开发过程的一些相关方面;本文稍后将 +更详细地讨论其中的大部分内容。考虑: + +- 所有Linux用户都可以使用合并到主线内核中的代码。它将自动出现在所有启用它的 + 发行版上。不需要驱动程序磁盘、下载,也不需要为多个发行版的多个版本提供支持; + 对于开发人员和用户来说,这一切都是可行的。并入主线解决了大量的分布和支持问题 + +- 当内核开发人员努力维护一个稳定的用户空间接口时,内部内核API处于不断变化之中. + 缺乏一个稳定的内部接口是一个深思熟虑的设计决策;它允许在任何时候进行基本的改 + 进,并产生更高质量的代码。但该策略的一个结果是,如果要使用新的内核,任何树外 + 代码都需要持续的维护。维护树外代码需要大量的工作才能使代码保持工作状态。 + + 相反,位于主线中的代码不需要这样做,因为一个简单的规则要求进行API更改的任何 + 开发人员也必须修复由于该更改而破坏的任何代码。因此,合并到主线中的代码大大 + 降低了维护成本。 + +- 除此之外,内核中的代码通常会被其他开发人员改进。令人惊讶的结果可能来自授权 + 您的用户社区和客户改进您的产品。 + +- 内核代码在合并到主线之前和之后都要经过审查。不管原始开发人员的技能有多强, + 这个审查过程总是能找到改进代码的方法。审查经常发现严重的错误和安全问题。 + 这对于在封闭环境中开发的代码尤其如此;这种代码从外部开发人员的审查中获益 + 匪浅。树外代码是低质量代码。 + +- 参与开发过程是您影响内核开发方向的方式。旁观者的抱怨会被听到,但是活跃的 + 开发人员有更强的声音——并且能够实现使内核更好地满足其需求的更改。 + +- 当单独维护代码时,总是存在第三方为类似功能提供不同实现的可能性。如果发生 + 这种情况,合并代码将变得更加困难——甚至到了不可能的地步。然后,您将面临以下 + 令人不快的选择:(1)无限期地维护树外的非标准特性,或(2)放弃代码并将用户 + 迁移到树内版本。 + +- 代码的贡献是使整个过程工作的根本。通过贡献代码,您可以向内核添加新功能,并 + 提供其他内核开发人员使用的功能和示例。如果您已经为Linux开发了代码(或者 + 正在考虑这样做),那么您显然对这个平台的持续成功感兴趣;贡献代码是确保成功 + 的最好方法之一。 + +上述所有理由都适用于任何树外内核代码,包括以专有的、仅二进制形式分发的代码。 +然而,在考虑任何类型的纯二进制内核代码分布之前,还需要考虑其他因素。这些包括: + +- 围绕专有内核模块分发的法律问题充其量是模糊的;相当多的内核版权所有者认为, + 大多数仅限二进制的模块是内核的派生产品,因此,它们的分发违反了GNU通用公共 + 许可证(下面将详细介绍)。您的作者不是律师,本文档中的任何内容都不可能被 + 视为法律建议。封闭源代码模块的真实法律地位只能由法院决定。但不管怎样,困扰 + 这些模块的不确定性仍然存在。 + +- 二进制模块大大增加了调试内核问题的难度,以至于大多数内核开发人员甚至都不会 + 尝试。因此,只分发二进制模块将使您的用户更难从社区获得支持。 + +- 对于只支持二进制的模块的发行者来说,支持也更加困难,他们必须为他们希望支持 + 的每个发行版和每个内核版本提供一个版本的模块。为了提供相当全面的覆盖范围, + 可能需要一个模块的几十个构建,并且每次升级内核时,您的用户都必须单独升级 + 您的模块。 + +- 上面提到的关于代码评审的所有问题都更加存在于封闭源代码。由于该代码根本不可 + 用,因此社区无法对其进行审查,毫无疑问,它将存在严重问题。 + +尤其是嵌入式系统的制造商,可能会倾向于忽视本节中所说的大部分内容,因为他们 +相信自己正在商用一种使用冻结内核版本的独立产品,在发布后不需要再进行开发。 +这个论点忽略了广泛的代码审查的价值以及允许用户向产品添加功能的价值。但这些 +产品也有有限的商业寿命,之后必须发布新版本的产品。在这一点上,代码在主线上 +并得到良好维护的供应商将能够更好地占位,以使新产品快速上市。 + +许可 +---- + +代码是根据一些许可证提供给Linux内核的,但是所有代码都必须与GNU通用公共许可 +证(GPLV2)的版本2兼容,该版本是覆盖整个内核分发的许可证。在实践中,这意味 +着所有代码贡献都由GPLv2(可选地,语言允许在更高版本的GPL下分发)或3子句BSD +许可(New BSD License, 译者注)覆盖。任何不包含在兼容许可证中的贡献都不会 +被接受到内核中。 + +贡献给内核的代码不需要(或请求)版权分配。合并到主线内核中的所有代码都保留 +其原始所有权;因此,内核现在拥有数千个所有者。 + +这种所有权结构的一个暗示是,任何改变内核许可的尝试都注定会失败。很少有实际 +的场景可以获得所有版权所有者的同意(或者从内核中删除他们的代码)。因此,特 +别是,在可预见的将来,不可能迁移到GPL的版本3。 + +所有贡献给内核的代码都必须是合法的免费软件。因此,不接受匿名(或匿名)贡献 +者的代码。所有贡献者都需要在他们的代码上“sign off”,声明代码可以在GPL下与内 +核一起分发。无法提供未被其所有者许可为免费软件的代码,或可能为内核造成版权 +相关问题的代码(例如,由缺乏适当保护的反向工程工作派生的代码)不能被接受。 + +有关版权相关问题的问题在Linux开发邮件列表中很常见。这样的问题通常会得到不少 +答案,但要记住,回答这些问题的人不是律师,不能提供法律咨询。如果您有关于 +Linux源代码的法律问题,那么与了解该领域的律师交流是无法替代的。依靠从技术 +邮件列表中获得的答案是一件冒险的事情。 + diff --git a/Documentation/translations/zh_CN/process/2.Process.rst b/Documentation/translations/zh_CN/process/2.Process.rst new file mode 100644 index 000000000000..ceb733bb0294 --- /dev/null +++ b/Documentation/translations/zh_CN/process/2.Process.rst @@ -0,0 +1,360 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/2.Process.rst <development_process>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_process: + +开发流程如何工作 +================ + +90年代早期的Linux内核开发是一件相当松散的事情,涉及的用户和开发人员相对较 +少。由于拥有数以百万计的用户群,并且在一年的时间里有大约2000名开发人员参与 +进来,内核因此必须发展许多流程来保持开发的顺利进行。要成为流程的有效组成 +部分,需要对流程的工作方式有一个扎实的理解。 + +总览 +---- + +内核开发人员使用一个松散的基于时间的发布过程,每两到三个月发布一次新的主要 +内核版本。最近的发布历史记录如下: + + ====== ================= + 4.11 四月 30, 2017 + 4.12 七月 2, 2017 + 4.13 九月 3, 2017 + 4.14 十一月 12, 2017 + 4.15 一月 28, 2018 + 4.16 四月 1, 2018 + ====== ================= + +每4.x版本都是一个主要的内核版本,具有新特性、内部API更改等等。一个典型的4.x +版本包含大约13000个变更集,变更了几十万行代码。因此,4.x是Linux内核开发的前 +沿;内核使用滚动开发模型,不断集成重大变化。 + +对于每个版本的补丁合并,遵循一个相对简单的规则。在每个开发周期的开始,“合并 +窗口”被打开。当时,被认为足够稳定(并且被开发社区接受)的代码被合并到主线内 +核中。在这段时间内,新开发周期的大部分变更(以及所有主要变更)将以接近每天 +1000次变更(“补丁”或“变更集”)的速度合并。 + +(顺便说一句,值得注意的是,合并窗口期间集成的更改并不是凭空产生的;它们是 +提前收集、测试和分级的。稍后将详细描述该过程的工作方式)。 + +合并窗口持续大约两周。在这段时间结束时,LinusTorvalds将声明窗口已关闭,并 +释放第一个“rc”内核。例如,对于目标为4.14的内核,在合并窗口结束时发生的释放 +将被称为4.14-rc1。RC1版本是一个信号,表示合并新特性的时间已经过去,稳定下一 +个内核的时间已经开始。 + +在接下来的6到10周内,只有修复问题的补丁才应该提交给主线。有时会允许更大的 +更改,但这种情况很少发生;试图在合并窗口外合并新功能的开发人员往往会受到不 +友好的接待。一般来说,如果您错过了给定特性的合并窗口,最好的做法是等待下一 +个开发周期。(对于以前不支持的硬件,偶尔会对驱动程序进行例外;如果它们不 +改变已有代码,则不会导致回归,并且应该可以随时安全地添加)。 + +随着修复程序进入主线,补丁速度将随着时间的推移而变慢。Linus大约每周发布一次 +新的-rc内核;一个正常的系列将在-rc6和-rc9之间,内核被认为足够稳定并最终发布。 +然后,整个过程又重新开始了。 + +例如,这里是4.16的开发周期进行情况(2018年的所有日期): + + ============== ============================== + 一月 28 4.15 稳定版发布 + 二月 11 4.16-rc1, 合并窗口关闭 + 二月 18 4.16-rc2 + 二月 25 4.16-rc3 + 三月 4 4.16-rc4 + 三月 11 4.16-rc5 + 三月 18 4.16-rc6 + 三月 25 4.16-rc7 + 四月 1 4.16 稳定版发布 + ============== ============================== + +开发人员如何决定何时结束开发周期并创建稳定的版本?使用的最重要的指标是以前 +版本的回归列表。不欢迎出现任何错误,但是那些破坏了以前能工作的系统的错误被 +认为是特别严重的。因此,导致回归的补丁是不受欢迎的,很可能在稳定期内删除。 + +开发人员的目标是在稳定发布之前修复所有已知的回归。在现实世界中,这种完美是 +很难实现的;在这种规模的项目中,变量太多了。有一点,延迟最终版本只会使问题 +变得更糟;等待下一个合并窗口的一堆更改将变大,从而在下次创建更多的回归错误。 +因此,大多数4.x内核都有一些已知的回归错误,不过,希望没有一个是严重的。 + +一旦一个稳定的版本发布,它正在进行的维护工作就被移交给“稳定团队”,目前由 +Greg Kroah-Hartman组成。稳定团队将使用4.x.y编号方案不定期的发布稳定版本的更 +新。要加入更新版本,补丁程序必须(1)修复一个重要的bug,(2)已经合并到 +下一个开发主线中。内核通常会在超过其初始版本的一个以上的开发周期内接收稳定 +的更新。例如,4.13内核的历史如下 + + ============== =============================== + 九月 3 4.13 稳定版发布 + 九月 13 4.13.1 + 九月 20 4.13.2 + 九月 27 4.13.3 + 十月 5 4.13.4 + 十月 12 4.13.5 + ... ... + 十一月 24 4.13.16 + ============== =============================== + +4.13.16是4.13版本的最终稳定更新。 + +有些内核被指定为“长期”内核;它们将得到更长时间的支持。在本文中,当前的长期 +内核及其维护者是: + + ====== ====================== ============================== + 3.16 Ben Hutchings (长期稳定内核) + 4.1 Sasha Levin + 4.4 Greg Kroah-Hartman (长期稳定内核) + 4.9 Greg Kroah-Hartman + 4.14 Greg Kroah-Hartman + ====== ====================== ============================== + +为长期支持选择内核纯粹是维护人员有必要和时间来维护该版本的问题。目前还没有 +为即将发布的任何特定版本提供长期支持的已知计划。 + +补丁的生命周期 +-------------- + +补丁不会直接从开发人员的键盘进入主线内核。相反,有一个稍微复杂(如果有些非 +正式)的过程,旨在确保对每个补丁进行质量审查,并确保每个补丁实现了一个在主线 +中需要的更改。对于小的修复,这个过程可能会很快发生,或者,在大的和有争议的 +变更的情况下,会持续数年。许多开发人员的挫折来自于对这个过程缺乏理解或者 +试图绕过它。 + +为了减少这种挫折感,本文将描述补丁如何进入内核。下面是一个介绍,它以某种 +理想化的方式描述了这个过程。更详细的过程将在后面的章节中介绍。 + +补丁程序经历的阶段通常是: + +- 设计。这就是补丁的真正需求——以及满足这些需求的方式——的所在。设计工作通常 + 是在不涉及社区的情况下完成的,但是如果可能的话,最好是在公开的情况下完成 + 这项工作;这样可以节省很多稍后再重新设计的时间。 + +- 早期评审。补丁被发布到相关的邮件列表中,列表中的开发人员会回复他们可能有 + 的任何评论。如果一切顺利的话,这个过程应该会发现补丁的任何主要问题。 + +- 更广泛的评审。当补丁接近准备好纳入主线时,它应该被相关的子系统维护人员 + 接受——尽管这种接受并不能保证补丁会一直延伸到主线。补丁将出现在维护人员的 + 子系统树中,并进入 -next 树(如下所述)。当流程工作时,此步骤将导致对补丁 + 进行更广泛的审查,并发现由于将此补丁与其他人所做的工作集成而导致的任何 + 问题。 + +- 请注意,大多数维护人员也有日常工作,因此合并补丁可能不是他们的最高优先级。 + 如果您的补丁程序得到了关于所需更改的反馈,那么您应该进行这些更改,或者为 + 不应该进行这些更改的原因辩护。如果您的补丁没有评审意见,但没有被其相应的 + 子系统或驱动程序维护者接受,那么您应该坚持不懈地将补丁更新到当前内核,使 + 其干净地应用,并不断地将其发送以供审查和合并。 + +- 合并到主线。最终,一个成功的补丁将被合并到由LinusTorvalds管理的主线存储库 + 中。此时可能会出现更多的评论和/或问题;开发人员应对这些问题并解决出现的 + 任何问题很重要。 + +- 稳定版发布。可能受补丁影响的用户数量现在很大,因此可能再次出现新的问题。 + +- 长期维护。虽然开发人员在合并代码后可能会忘记代码,但这种行为往往会给开发 + 社区留下不良印象。合并代码消除了一些维护负担,因为其他代码将修复由API + 更改引起的问题。但是,如果代码要长期保持有用,原始开发人员应该继续为 + 代码负责。 + +内核开发人员(或他们的雇主)犯的最大错误之一是试图将流程简化为一个 +“合并到主线”步骤。这种方法总是会让所有相关人员感到沮丧。 + +补丁如何进入内核 +---------------- + +只有一个人可以将补丁合并到主线内核存储库中:LinusTorvalds。但是,在进入 +2.6.38内核的9500多个补丁中,只有112个(大约1.3%)是由Linus自己直接选择的。 +内核项目已经发展到一个规模,没有一个开发人员可以在没有支持的情况下检查和 +选择每个补丁。内核开发人员处理这种增长的方式是通过使用围绕信任链构建的 +助理系统。 + +内核代码库在逻辑上被分解为一组子系统:网络、特定的体系结构支持、内存管理、 +视频设备等。大多数子系统都有一个指定的维护人员,开发人员对该子系统中的代码 +负有全部责任。这些子系统维护者(松散地)是他们所管理的内核部分的守护者; +他们(通常)会接受一个补丁以包含到主线内核中。 + +子系统维护人员每个人都使用git源代码管理工具管理自己版本的内核源代码树。Git +等工具(以及Quilt或Mercurial等相关工具)允许维护人员跟踪补丁列表,包括作者 +信息和其他元数据。在任何给定的时间,维护人员都可以确定他或她的存储库中的哪 +些补丁在主线中找不到。 + +当合并窗口打开时,顶级维护人员将要求Linus从其存储库中“拉出”他们为合并选择 +的补丁。如果Linus同意,补丁流将流向他的存储库,成为主线内核的一部分。 +Linus对拉操作中接收到的特定补丁的关注程度各不相同。很明显,有时他看起来很 +关注。但是,作为一般规则,Linus相信子系统维护人员不会向上游发送坏补丁。 + +子系统维护人员反过来也可以从其他维护人员那里获取补丁。例如,网络树是由首先 +在专用于网络设备驱动程序、无线网络等的树中积累的补丁构建的。此存储链可以 +任意长,但很少超过两个或三个链接。由于链中的每个维护者都信任那些管理较低 +级别树的维护者,所以这个过程称为“信任链”。 + +显然,在这样的系统中,获取内核补丁取决于找到正确的维护者。直接向Linus发送 +补丁通常不是正确的方法。 + +Next 树 +------- + +子系统树链引导补丁流到内核,但它也提出了一个有趣的问题:如果有人想查看为 +下一个合并窗口准备的所有补丁怎么办?开发人员将感兴趣的是,还有什么其他的 +更改有待解决,以查看是否存在需要担心的冲突;例如,更改核心内核函数原型的 +修补程序将与使用该函数旧形式的任何其他修补程序冲突。审查人员和测试人员希望 +在所有这些变更到达主线内核之前,能够访问它们的集成形式中的变更。您可以从所有 +有趣的子系统树中提取更改,但这将是一项大型且容易出错的工作。 + +答案以-next树的形式出现,在这里子系统树被收集以供测试和审查。Andrew Morton +维护的这些旧树被称为“-mm”(用于内存管理,这就是它的启动名字)。-mm 树集成了 +一长串子系统树中的补丁;它还包含一些旨在帮助调试的补丁。 + +除此之外,-mm 还包含大量由Andrew直接选择的补丁。这些补丁可能已经发布在邮件 +列表上,或者它们可能应用于内核中没有指定子系统树的部分。结果,-mm 作为一种 +最后手段的子系统树运行;如果没有其他明显的路径可以让补丁进入主线,那么它很 +可能以-mm 结束。累积在-mm 中的各种补丁最终将被转发到适当的子系统树,或者直接 +发送到Linus。在典型的开发周期中,大约5-10%的补丁通过-mm 进入主线。 + +当前-mm 补丁可在“mmotm”(-mm of the moment)目录中找到,地址: + + http://www.ozlabs.org/~akpm/mmotm/ + +然而,使用mmotm树可能是一种令人沮丧的体验;它甚至可能无法编译。 + +下一个周期补丁合并的主要树是linux-next,由Stephen Rothwell 维护。根据设计 +linux-next 是下一个合并窗口关闭后主线的快照。linux-next树在Linux-kernel 和 +Linux-next 邮件列表中发布,可从以下位置下载: + + http://www.kernel.org/pub/linux/kernel/next/ + +Linux-next 已经成为内核开发过程中不可或缺的一部分;在一个给定的合并窗口中合并 +的所有补丁都应该在合并窗口打开之前的一段时间内找到进入Linux-next 的方法。 + +Staging 树 +---------- + +内核源代码树包含drivers/staging/directory,其中有许多驱动程序或文件系统的 +子目录正在被添加到内核树中。它们然需要更多的工作的时候可以保留在 +driver/staging目录中;一旦完成,就可以将它们移到内核中。这是一种跟踪不符合 +Linux内核编码或质量标准的驱动程序的方法,但人们可能希望使用它们并跟踪开发。 + +Greg Kroah Hartman 目前负责维护staging 树。仍需要工作的驱动程序将发送给他, +每个驱动程序在drivers/staging/中都有自己的子目录。除了驱动程序源文件之外, +目录中还应该有一个TODO文件。todo文件列出了驱动程序需要接受的挂起的工作, +以及驱动程序的任何补丁都应该抄送的人员列表。当前的规则要求,staging的驱动 +程序必须至少正确编译。 + +Staging 是一种相对容易的方法,可以让新的驱动程序进入主线,幸运的是,他们会 +引起其他开发人员的注意,并迅速改进。然而,进入staging并不是故事的结尾; +staging中没有看到常规进展的代码最终将被删除。经销商也倾向于相对不愿意使用 +staging驱动程序。因此,在成为一名合适的主线驱动的路上,staging 充其量只是 +一个停留。 + +工具 +---- + +从上面的文本可以看出,内核开发过程在很大程度上依赖于在不同方向上聚集补丁的 +能力。如果没有适当强大的工具,整个系统将无法在任何地方正常工作。关于如何使用 +这些工具的教程远远超出了本文档的范围,但是还是有一些指南的空间。 + +到目前为止,内核社区使用的主要源代码管理系统是git。Git是在自由软件社区中开发 +的许多分布式版本控制系统之一。它非常适合内核开发,因为它在处理大型存储库和 +大量补丁时性能非常好。它还有一个难以学习和使用的名声,尽管随着时间的推移它 +变得更好了。对于内核开发人员来说,对Git的某种熟悉几乎是一种要求;即使他们不 +将它用于自己的工作,他们也需要Git来跟上其他开发人员(以及主线)正在做的事情。 + +现在几乎所有的Linux发行版都打包了Git。主页位于: + + http://git-scm.com/ + +那个页面有指向文档和教程的指针。 + +在不使用git的内核开发人员中,最流行的选择几乎肯定是mercurial: + + http://www.seleric.com/mercurial/ + +Mercurial与Git共享许多特性,但它提供了一个界面,许多人觉得它更易于使用。 + +另一个值得了解的工具是quilt: + + http://savannah.nongnu.org/projects/quilt + +Quilt 是一个补丁管理系统,而不是源代码管理系统。它不会随着时间的推移跟踪历史; +相反,它面向根据不断发展的代码库跟踪一组特定的更改。一些主要的子系统维护人员 +使用Quilt来管理打算向上游移动的补丁。对于某些树的管理(例如-mm),quilt 是 +最好的工具。 + +邮件列表 +-------- + +大量的Linux内核开发工作是通过邮件列表完成的。如果不在某个地方加入至少一个列表, +就很难成为社区中一个功能完备的成员。但是,Linux邮件列表对开发人员来说也是一个 +潜在的危险,他们可能会被一堆电子邮件淹没,违反Linux列表上使用的约定,或者 +两者兼而有之。 + +大多数内核邮件列表都在vger.kernel.org上运行;主列表位于: + + http://vger.kernel.org/vger-lists.html + +不过,也有一些列表托管在别处;其中一些列表位于lists.redhat.com。 + +当然,内核开发的核心邮件列表是linux-kernel。这个名单是一个令人生畏的地方; +每天的信息量可以达到500条,噪音很高,谈话技术性很强,参与者并不总是表现出 +高度的礼貌。但是,没有其他地方可以让内核开发社区作为一个整体聚集在一起; +避免使用此列表的开发人员将错过重要信息。 + +有一些提示可以帮助在linux-kernel生存: + +- 将邮件转移到单独的文件夹,而不是主邮箱。我们必须能够持续地忽略洪流。 + +- 不要试图跟踪每一次谈话-其他人都不会。重要的是要对感兴趣的主题(尽管请 + 注意,长时间的对话可以在不更改电子邮件主题行的情况下偏离原始主题)和参与 + 的人进行筛选。 + +- 不要挑事。如果有人试图激起愤怒的反应,忽略他们。 + +- 当响应Linux内核电子邮件(或其他列表上的电子邮件)时,请为所有相关人员保留 + cc:header。如果没有强有力的理由(如明确的请求),则不应删除收件人。一定要 + 确保你要回复的人在cc:list中。这个惯例也使你不必在回复邮件时明确要求被抄送。 + +- 在提出问题之前,搜索列表档案(和整个网络)。有些开发人员可能会对那些显然 + 没有完成家庭作业的人感到不耐烦。 + +- 避免贴顶帖(把你的答案放在你要回复的引文上面的做法)。这会让你的回答更难 + 理解,印象也很差。 + +- 询问正确的邮件列表。linux-kernel 可能是通用的讨论点,但它不是从所有子系统 + 中寻找开发人员的最佳场所。 + +最后一点——找到正确的邮件列表——是开发人员出错的常见地方。在Linux内核上提出与 +网络相关的问题的人几乎肯定会收到一个礼貌的建议,转而在netdev列表上提出, +因为这是大多数网络开发人员经常出现的列表。还有其他列表可用于scsi、 +video4linux、ide、filesystem等子系统。查找邮件列表的最佳位置是与内核源代码 +一起打包的MAINTAINERS文件。 + +开始内核开发 +------------ + +关于如何开始内核开发过程的问题很常见——来自个人和公司。同样常见的是错误,这 +使得关系的开始比必须的更困难。 + +公司通常希望聘请知名的开发人员来启动开发团队。实际上,这是一种有效的技术。 +但它也往往是昂贵的,而且没有增长经验丰富的内核开发人员储备。考虑到时间的 +投入,可以让内部开发人员加快Linux内核的开发速度。花这个时间可以让雇主拥有 +一批了解内核和公司的开发人员,他们也可以帮助培训其他人。从中期来看,这往往 +是更有利可图的方法。 + +可以理解的是,单个开发人员往往对起步感到茫然。从一个大型项目开始可能会很 +吓人;人们往往想先用一些较小的东西来测试水域。这是一些开发人员开始创建修补 +拼写错误或轻微编码风格问题的补丁的地方。不幸的是,这样的补丁会产生一定程度 +的噪音,这会分散整个开发社区的注意力,因此,越来越多的人看不起它们。希望向 +社区介绍自己的新开发人员将无法通过这些方式获得他们想要的那种接待。 + +Andrew Morton 为有抱负的内核开发人员提供了这个建议 + +:: + + 所有内核初学者的No.1项目肯定是“确保内核在所有的机器上,你可以触摸 + 到的,始终运行良好" 通常这样做的方法是与其他人一起解决问题(这 + 可能需要坚持!)但这很好——这是内核开发的一部分 + +(http://lwn.net/articles/283982/) + +在没有明显问题需要解决的情况下,建议开发人员查看当前的回归和开放式错误列表. +解决需要修复的问题没有任何缺点;通过解决这些问题,开发人员将获得处理过程的 +经验,同时与开发社区的其他人建立尊重。 diff --git a/Documentation/translations/zh_CN/process/3.Early-stage.rst b/Documentation/translations/zh_CN/process/3.Early-stage.rst new file mode 100644 index 000000000000..b8676aec6005 --- /dev/null +++ b/Documentation/translations/zh_CN/process/3.Early-stage.rst @@ -0,0 +1,161 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_early_stage: + +早期规划 +======== + +当考虑一个Linux内核开发项目时,很可能会直接跳进去开始编码。然而,与任何重要 +的项目一样,成功的许多基础最好是在第一行代码编写之前就做好了。在早期计划和 +沟通中花费一些时间可以节省更多的时间。 + +详述问题 +-------- + +与任何工程项目一样,成功的内核增强从要解决的问题的清晰描述开始。在某些情况 +下,这个步骤很容易:例如,当某个特定硬件需要驱动程序时。不过,在其他方面, +将实际问题与建议的解决方案混淆是很有诱惑力的,这可能会导致困难。 + +举个例子:几年前,使用Linux音频的开发人员寻求一种方法来运行应用程序,而不因 +系统延迟过大而导致退出或其他工件。他们得到的解决方案是一个内核模块,旨在连 +接到Linux安全模块(LSM)框架中;这个模块可以配置为允许特定的应用程序访问 +实时调度程序。这个模块被实现并发送到Linux内核邮件列表,在那里它立即遇到问题。 + +对于音频开发人员来说,这个安全模块足以解决他们当前的问题。但是,对于更广泛的 +内核社区来说,这被视为对LSM框架的滥用(LSM框架并不打算授予他们原本不具备的 +进程特权),并对系统稳定性造成风险。他们首选的解决方案包括短期的通过rlimit +机制进行实时调度访问,以及长期的减少延迟的工作。 + +然而,音频社区看不到他们实施的特定解决方案的过去;他们不愿意接受替代方案。 +由此产生的分歧使这些开发人员对整个内核开发过程感到失望;其中一个开发人员返回 +到音频列表并发布了以下内容: + + 有很多非常好的Linux内核开发人员,但他们往往会被一群傲慢的傻瓜所压倒。 + 试图向这些人传达用户需求是浪费时间。他们太“聪明”了,根本听不到少数人 + 的话。 + +(http://lwn.net/articles/131776/) + +实际情况不同;与特定模块相比,内核开发人员更关心系统稳定性、长期维护以及找到 +正确的问题解决方案。这个故事的寓意是把重点放在问题上——而不是具体的解决方案 +上——并在投入创建代码之前与开发社区讨论这个问题。 + +因此,在考虑一个内核开发项目时,我们应该得到一组简短问题的答案: + + - 究竟需要解决的问题是什么? + + - 受此问题影响的用户是谁?解决方案应该解决哪些用例? + + - 内核现在为何没能解决这个问题? + +只有这样,才能开始考虑可能的解决方案。 + + +早期讨论 +-------- + +在计划内核开发项目时,在开始实施之前与社区进行讨论是很有意义的。早期沟通可以 +通过多种方式节省时间和麻烦: + + - 很可能问题是由内核以您不理解的方式解决的。Linux内核很大,具有许多不明显 + 的特性和功能。并不是所有的内核功能都像人们所希望的那样有文档记录,而且很 + 容易遗漏一些东西。你的作者发出了一个完整的驱动程序,复制了一个新作者不 + 知道的现有驱动程序。重新设计现有轮子的代码不仅浪费,而且不会被接受到主线 + 内核中。 + + - 建议的解决方案中可能有一些元素不适用于主线合并。在编写代码之前,最好先 + 了解这样的问题。 + + - 其他开发人员完全有可能考虑过这个问题;他们可能有更好的解决方案的想法,并且 + 可能愿意帮助创建这个解决方案。 + +在内核开发社区的多年经验给了我们一个明确的教训:闭门设计和开发的内核代码总是 +有一些问题,这些问题只有在代码发布到社区中时才会被发现。有时这些问题很严重, +需要数月或数年的努力才能使代码达到内核社区的标准。一些例子包括: + + - 设计并实现了单处理器系统的DeviceScape网络栈。只有使其适合于多处理器系统, + 才能将其合并到主线中。在代码中改装锁等等是一项困难的任务;因此,这段代码 + (现在称为mac80211)的合并被推迟了一年多。 + + - Reiser4文件系统包含许多功能,核心内核开发人员认为这些功能应该在虚拟文件 + 系统层中实现。它还包括一些特性,这些特性在不将系统暴露于用户引起的死锁的 + 情况下是不容易实现的。这些问题的最新发现——以及对其中一些问题的拒绝——已经 + 导致Reiser4远离了主线内核。 + + - Apparmor安全模块以被认为不安全和不可靠的方式使用内部虚拟文件系统数据结构。 + 这种担心(包括其他)使Apparmor多年不在主线上。 + +在每一种情况下,通过与内核开发人员的早期讨论,可以避免大量的痛苦和额外的工作。 + +找谁交流 +-------- + +当开发人员决定公开他们的计划时,下一个问题是:我们从哪里开始?答案是找到正确 +的邮件列表和正确的维护者。对于邮件列表,最好的方法是在维护者(MAINTAINERS)文件 +中查找要发布的相关位置。如果有一个合适的子系统列表,那么发布它通常比在Linux +内核上发布更可取;您更有可能接触到在相关子系统中具有专业知识的开发人员,并且 +环境可能具支持性。 + +找到维护人员可能会有点困难。同样,维护者文件是开始的地方。但是,该文件往往不总 +是最新的,并且并非所有子系统都在那里表示。实际上,维护者文件中列出的人员可能 +不是当前实际担任该角色的人员。因此,当对联系谁有疑问时,一个有用的技巧是使用 +git(尤其是“git-log”)查看感兴趣的子系统中当前活动的用户。看看谁在写补丁, +如果有人的话,谁会在这些补丁上加上用线签名的。这些人将是帮助新开发项目的最佳 +人选。 + +找到合适的维护者的任务有时是非常具有挑战性的,以至于内核开发人员添加了一个 +脚本来简化过程: + +:: + + .../scripts/get_maintainer.pl + +当给定“-f”选项时,此脚本将返回给定文件或目录的当前维护者。如果在命令行上传递 +了一个补丁,它将列出可能接收补丁副本的维护人员。有许多选项可以调节 +get_maintainer.pl搜索维护者的难易程度;请小心使用更具攻击性的选项,因为最终 +可能会包括对您正在修改的代码没有真正兴趣的开发人员。 + +如果所有其他方法都失败了,那么与Andrew Morton交谈可以成为一种有效的方法来跟踪 +特定代码段的维护人员。 + +何时邮寄? +---------- + +如果可能的话,在早期阶段发布你的计划只会有帮助。描述正在解决的问题以及已经 +制定的关于如何实施的任何计划。您可以提供的任何信息都可以帮助开发社区为项目 +提供有用的输入。 + +在这个阶段可能发生的一件令人沮丧的事情不是敌对的反应,而是很少或根本没有 +反应。可悲的事实是:(1)内核开发人员往往很忙;(2)不缺少有宏伟计划和很少 +代码(甚至代码前景)支持他们的人;(3)没有人有义务审查或评论别人发表的 +想法。除此之外,高级设计常常隐藏一些问题,这些问题只有在有人真正尝试实现 +这些设计时才会被发现;因此,内核开发人员宁愿看到代码。 + +如果发表评论的请求在评论的方式上没有什么效果,不要假设这意味着对项目没有 +兴趣。不幸的是,你也不能假设你的想法没有问题。在这种情况下,最好的做法是 +继续进行,把你的进展随时通知社区。 + +获得官方认可 +----------------------- + +如果您的工作是在公司环境中完成的,就像大多数Linux内核工作一样,显然,在您将 +公司的计划或代码发布到公共邮件列表之前,必须获得适当授权的经理的许可。发布 +不确定是否兼容GPL的代码可能是有特别问题的;公司的管理层和法律人员越早能够就 +发布内核开发项目达成一致,对参与的每个人都越好。 + +一些读者可能会认为他们的核心工作是为了支持还没有正式承认存在的产品。将雇主 +的计划公布在公共邮件列表上可能不是一个可行的选择。在这种情况下,有必要考虑 +保密是否真的是必要的;通常不需要把开发计划关在门内。 + +也就是说,有些情况下,一家公司在开发过程的早期就不能合法地披露其计划。拥有 +经验丰富的内核开发人员的公司可以选择以开环的方式进行,前提是他们以后能够避免 +严重的集成问题。对于没有这种内部专业知识的公司,最好的选择往往是聘请外部 +开发商根据保密协议审查计划。Linux基金会运行了一个NDA程序,旨在帮助解决这种 +情况; + + http://www.linuxfoundation.org/en/NDA_program + +这种审查通常足以避免以后出现严重问题,而无需公开披露项目。 diff --git a/Documentation/translations/zh_CN/process/4.Coding.rst b/Documentation/translations/zh_CN/process/4.Coding.rst new file mode 100644 index 000000000000..5301e9d55255 --- /dev/null +++ b/Documentation/translations/zh_CN/process/4.Coding.rst @@ -0,0 +1,290 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_coding: + +使代码正确 +====================== + +虽然对于一个坚实的、面向社区的设计过程有很多话要说,但是任何内核开发项目的 +证明都在生成的代码中。它是将由其他开发人员检查并合并(或不合并)到主线树中 +的代码。所以这段代码的质量决定了项目的最终成功。 + +本节将检查编码过程。我们将从内核开发人员出错的几种方式开始。然后重点将转移 +到正确的事情和可以帮助这个任务的工具上。 + +陷阱 +---- + +编码风格 +******** + +内核长期以来都有一种标准的编码风格,如 +:ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>` +中所述。在大部分时间里,该文件中描述的政策被认为至多是建议性的。因此,内核 +中存在大量不符合编码风格准则的代码。代码的存在会给内核开发人员带来两个独立 +的危害。 + +首先,要相信内核编码标准并不重要,也不强制执行。事实上,如果没有按照标准对代 +码进行编码,那么向内核添加新代码是非常困难的;许多开发人员甚至会在审查代码之 +前要求对代码进行重新格式化。一个与内核一样大的代码库需要一些统一的代码,以使 +开发人员能够快速理解其中的任何部分。所以已经没有空间来存放奇怪的格式化代码了。 + +偶尔,内核的编码风格会与雇主的强制风格发生冲突。在这种情况下,内核的风格必须 +在代码合并之前获胜。将代码放入内核意味着以多种方式放弃一定程度的控制权——包括 +控制代码的格式化方式。 + +另一个陷阱是假定已经在内核中的代码迫切需要编码样式的修复。开发人员可能会开始 +生成重新格式化补丁,作为熟悉过程的一种方式,或者作为将其名称写入内核变更日志 +的一种方式,或者两者兼而有之。但是纯编码风格的修复被开发社区视为噪音;它们往 +往受到冷遇。因此,最好避免使用这种类型的补丁。由于其他原因,在处理一段代码的 +同时修复它的样式是很自然的,但是编码样式的更改不应该仅为了更改而进行。 + +编码风格的文档也不应该被视为绝对的法律,这是永远不会被违反的。如果有一个很好 +的理由反对这种样式(例如,如果拆分为适合80列限制的行,那么它的可读性就会大大 +降低),那么就这样做。 + +请注意,您还可以使用 ``clang-format`` 工具来帮助您处理这些规则,自动重新格式 +化部分代码,并查看完整的文件,以发现编码样式错误、拼写错误和可能的改进。它还 +可以方便地进行排序,包括对齐变量/宏、回流文本和其他类似任务。有关详细信息,请 +参阅文件 :ref:`Documentation/process/clang-format.rst <clangformat>` + +抽象层 +****** + +计算机科学教授教学生以灵活性和信息隐藏的名义广泛使用抽象层。当然,内核广泛 +地使用了抽象;任何涉及数百万行代码的项目都不能做到这一点并存活下来。但经验 +表明,过度或过早的抽象可能和过早的优化一样有害。抽象应用于所需的级别, +不要过度。 + +在一个简单的级别上,考虑一个函数的参数,该参数总是由所有调用方作为零传递。 +我们可以保留这个论点: 以防有人最终需要使用它提供的额外灵活性。不过,到那时, +实现这个额外参数的代码很有可能以某种从未被注意到的微妙方式被破坏——因为它从 +未被使用过。或者,当需要额外的灵活性时,它不会以符合程序员早期期望的方式来 +这样做。内核开发人员通常会提交补丁来删除未使用的参数;一般来说,首先不应该 +添加这些参数。 + +隐藏硬件访问的抽象层——通常允许大量的驱动程序在多个操作系统中使用——尤其不受 +欢迎。这样的层使代码变得模糊,可能会造成性能损失;它们不属于Linux内核。 + +另一方面,如果您发现自己从另一个内核子系统复制了大量的代码,那么现在是时候 +问一下,事实上,将这些代码中的一些提取到单独的库中,或者在更高的层次上实现 +这些功能是否有意义。在整个内核中复制相同的代码没有价值。 + +#ifdef 和预处理 +*************** + +C预处理器似乎给一些C程序员带来了强大的诱惑,他们认为它是一种有效地将大量灵 +活性编码到源文件中的方法。但是预处理器不是C,大量使用它会导致代码对其他人来 +说更难读取,对编译器来说更难检查正确性。大量的预处理器几乎总是代码需要一些 +清理工作的标志。 + +使用ifdef的条件编译实际上是一个强大的功能,它在内核中使用。但是很少有人希望 +看到代码被大量地撒上ifdef块。作为一般规则,ifdef的使用应尽可能限制在头文件 +中。有条件编译的代码可以限制函数,如果代码不存在,这些函数就会变成空的。然后 +编译器将悄悄地优化对空函数的调用。结果是代码更加清晰,更容易理解。 + +C预处理器宏存在许多危险,包括可能对具有副作用且没有类型安全性的表达式进行多 +重评估。如果您试图定义宏,请考虑创建一个内联函数。结果相同的代码,但是内联 +函数更容易读取,不会多次计算其参数,并且允许编译器对参数和返回值执行类型检查。 + +内联函数 +******** + +不过,内联函数本身也存在风险。程序员可以倾心于避免函数调用和用内联函数填充源 +文件所固有的效率。然而,这些功能实际上会降低性能。因为它们的代码在每个调用站 +点都被复制,所以它们最终会增加编译内核的大小。反过来,这会对处理器的内存缓存 +造成压力,从而大大降低执行速度。通常,内联函数应该非常小,而且相对较少。毕竟, +函数调用的成本并不高;大量内联函数的创建是过早优化的典型例子。 + +一般来说,内核程序员会忽略缓存效果,这会带来危险。在开始的数据结构课程中,经 +典的时间/空间权衡通常不适用于当代硬件。空间就是时间,因为一个大的程序比一个 +更紧凑的程序运行得慢。 + +最近的编译器在决定一个给定函数是否应该被内联方面扮演着越来越积极的角色。 +因此,“inline”关键字的自由放置可能不仅仅是过度的,它也可能是无关的。 + +锁 +** + +2006年5月,“deviceescape”网络堆栈在GPL下发布,并被纳入主线内核。这是一个受 +欢迎的消息;对Linux中无线网络的支持充其量被认为是不合格的,而deviceescape +堆栈提供了修复这种情况的承诺。然而,直到2007年6月(2.6.22),这段代码才真 +正进入主线。发生了什么? + +这段代码显示了许多闭门造车的迹象。但一个特别大的问题是,它并不是设计用于多 +处理器系统。在合并这个网络堆栈(现在称为mac80211)之前,需要对其进行一个锁 +方案的改造。 + +曾经,Linux内核代码可以在不考虑多处理器系统所带来的并发性问题的情况下进行 +开发。然而,现在,这个文件是写在双核笔记本电脑上的。即使在单处理器系统上, +为提高响应能力所做的工作也会提高内核内的并发性水平。编写内核代码而不考虑锁 +的日子已经过去很长了。 + +可以由多个线程并发访问的任何资源(数据结构、硬件寄存器等)必须由锁保护。新 +的代码应该记住这一要求;事后改装锁是一项相当困难的任务。内核开发人员应该花 +时间充分了解可用的锁原语,以便为作业选择正确的工具。显示对并发性缺乏关注的 +代码进入主线将很困难。 + +回归 +**** + +最后一个值得一提的危险是:它可能会引起改变(这可能会带来很大的改进),从而 +导致现有用户的某些东西中断。这种变化被称为“回归”,回归已经成为主线内核最不 +受欢迎的。除少数例外情况外,如果回归不能及时修正,会导致回归的变化将被取消。 +最好首先避免回归。 + +人们常常争论,如果回归让更多人可以工作,远超过产生问题,那么回归是合理的。 +如果它破坏的一个系统却为十个系统带来新的功能,为什么不进行更改呢?2007年7月, +Linus对这个问题给出了最佳答案: + +:: + 所以我们不会通过引入新问题来修复错误。那样的谎言很疯狂,没有人知道 + 你是否真的有进展。是前进两步,后退一步,还是向前一步,向后两步? + +(http://lwn.net/articles/243460/) + +一种特别不受欢迎的回归类型是用户空间ABI的任何变化。一旦接口被导出到用户空间, +就必须无限期地支持它。这一事实使得用户空间接口的创建特别具有挑战性:因为它们 +不能以不兼容的方式进行更改,所以必须第一次正确地进行更改。因此,用户空间界面 +总是需要大量的思考、清晰的文档和广泛的审查。 + + +代码检查工具 +------------ + +至少目前,编写无错误代码仍然是我们中很少人能达到的理想状态。不过,我们希望做 +的是,在代码进入主线内核之前,尽可能多地捕获并修复这些错误。为此,内核开发人 +员已经组装了一系列令人印象深刻的工具,可以自动捕获各种各样的模糊问题。计算机 +发现的任何问题都是一个以后不会困扰用户的问题,因此,只要有可能,就应该使用 +自动化工具。 + +第一步只是注意编译器产生的警告。当代版本的GCC可以检测(并警告)大量潜在错误。 +通常,这些警告都指向真正的问题。提交以供审阅的代码通常不会产生任何编译器警告。 +在消除警告时,注意了解真正的原因,并尽量避免“修复”,使警告消失而不解决其原因。 + +请注意,并非所有编译器警告都默认启用。使用“make EXTRA_CFLAGS=-W”构建内核以 +获得完整集合。 + +内核提供了几个配置选项,可以打开调试功能;大多数配置选项位于“kernel hacking” +子菜单中。对于任何用于开发或测试目的的内核,都应该启用其中几个选项。特别是, +您应该打开: + + - 启用 ENABLE_MUST_CHECK and FRAME_WARN 以获得一组额外的警告,以解决使用不 + 推荐使用的接口或忽略函数的重要返回值等问题。这些警告生成的输出可能是冗长 + 的,但您不必担心来自内核其他部分的警告。 + + - DEBUG_OBJECTS 将添加代码,以跟踪内核创建的各种对象的生存期,并在出现问题时 + 发出警告。如果要添加创建(和导出)自己的复杂对象的子系统,请考虑添加对对象 + 调试基础结构的支持。 + + - DEBUG_SLAB 可以发现各种内存分配和使用错误;它应该用于大多数开发内核。 + + - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP and DEBUG_MUTEXES 会发现许多常见的 + 锁定错误. + +还有很多其他调试选项,其中一些将在下面讨论。其中一些具有显著的性能影响,不应 +一直使用。但是,在学习可用选项上花费的一些时间可能会在短期内得到多次回报。 + +其中一个较重的调试工具是锁定检查器或“lockdep”。该工具将跟踪系统中每个锁 +(spinlock或mutex)的获取和释放、获取锁的相对顺序、当前中断环境等等。然后, +它可以确保总是以相同的顺序获取锁,相同的中断假设适用于所有情况,等等。换句话 +说,lockdep可以找到许多场景,在这些场景中,系统很少会死锁。在部署的系统中, +这种问题可能会很痛苦(对于开发人员和用户而言);LockDep允许提前以自动方式 +发现问题。具有任何类型的非普通锁定的代码在提交包含前应在启用lockdep的情况 +下运行。 + +作为一个勤奋的内核程序员,毫无疑问,您将检查任何可能失败的操作(如内存分配) +的返回状态。然而,事实上,最终的故障恢复路径可能完全没有经过测试。未测试的 +代码往往会被破坏;如果所有这些错误处理路径都被执行了几次,那么您可能对代码 +更有信心。 + +内核提供了一个可以做到这一点的错误注入框架,特别是在涉及内存分配的情况下。 +启用故障注入后,内存分配的可配置百分比将失败;这些失败可以限制在特定的代码 +范围内。在启用了故障注入的情况下运行,程序员可以看到当情况恶化时代码如何响 +应。有关如何使用此工具的详细信息,请参阅 +Documentation/fault-injection/fault-injection.txt。 + +使用“sparse”静态分析工具可以发现其他类型的错误。对于sparse,可以警告程序员 +用户空间和内核空间地址之间的混淆、big endian和small endian数量的混合、在需 +要一组位标志的地方传递整数值等等。sparse必须单独安装(如果您的分发服务器没 +有将其打包,可以在 https://sparse.wiki.kernel.org/index.php/Main_page)找到, +然后可以通过在make命令中添加“C=1”在代码上运行它。 + +“Coccinelle”工具 :ref:`http://coccinelle.lip6.fr/ <devtools_coccinelle>` +能够发现各种潜在的编码问题;它还可以为这些问题提出修复方案。在 +scripts/coccinelle目录下已经打包了相当多的内核“语义补丁”;运行 +“make coccicheck”将运行这些语义补丁并报告发现的任何问题。有关详细信息,请参阅 +:ref:`Documentation/dev-tools/coccinelle.rst <devtools_coccinelle>` + + +其他类型的可移植性错误最好通过为其他体系结构编译代码来发现。如果没有S/390系统 +或Blackfin开发板,您仍然可以执行编译步骤。可以在以下位置找到一组用于x86系统的 +大型交叉编译器: + + http://www.kernel.org/pub/tools/crosstool/ + +花一些时间安装和使用这些编译器将有助于避免以后的尴尬。 + +文档 +---- + +文档通常比内核开发规则更为例外。即便如此,足够的文档将有助于简化将新代码合并 +到内核中的过程,使其他开发人员的生活更轻松,并对您的用户有所帮助。在许多情况 +下,文件的添加已基本上成为强制性的。 + +任何补丁的第一个文档是其关联的变更日志。日志条目应该描述正在解决的问题、解决 +方案的形式、处理补丁的人员、对性能的任何相关影响,以及理解补丁可能需要的任何 +其他内容。确保changelog说明了为什么补丁值得应用;大量开发人员未能提供这些信息。 + +任何添加新用户空间界面的代码(包括新的sysfs或/proc文件)都应该包含该界面的 +文档,该文档使用户空间开发人员能够知道他们在使用什么。请参阅 +Documentation/abi/readme,了解如何格式化此文档以及需要提供哪些信息。 + +文件 :ref:`Documentation/admin-guide/kernel-parameters.rst <kernelparameters>` +描述了内核的所有引导时间参数。任何添加新参数的补丁都应该向该文件添加适当的 +条目。 + +任何新的配置选项都必须附有帮助文本,帮助文本清楚地解释了这些选项以及用户可能 +希望何时选择它们。 + +许多子系统的内部API信息通过专门格式化的注释进行记录;这些注释可以通过 +“kernel-doc”脚本以多种方式提取和格式化。如果您在具有kerneldoc注释的子系统中 +工作,则应该维护它们,并根据需要为外部可用的功能添加它们。即使在没有如此记录 +的领域中,为将来添加kerneldoc注释也没有坏处;实际上,这对于刚开始开发内核的人 +来说是一个有用的活动。这些注释的格式以及如何创建kerneldoc模板的一些信息可以在 +:ref:`Documentation/doc-guide/ <doc_guide>` 上找到。 + +任何阅读大量现有内核代码的人都会注意到,注释的缺失往往是最值得注意的。再一次, +对新代码的期望比过去更高;合并未注释的代码将更加困难。这就是说,人们几乎不希望 +用语言注释代码。代码本身应该是可读的,注释解释了更微妙的方面。 + +某些事情应该总是被注释。使用内存屏障时,应附上一行文字,解释为什么需要设置内存 +屏障。数据结构的锁定规则通常需要在某个地方解释。一般来说,主要数据结构需要全面 +的文档。应该指出单独代码位之间不明显的依赖性。任何可能诱使代码看门人进行错误的 +“清理”的事情都需要一个注释来说明为什么要这样做。等等。 + + +内部API更改 +----------- + +内核提供给用户空间的二进制接口不能被破坏,除非在最严重的情况下。相反,内核的 +内部编程接口是高度流动的,当需要时可以更改。如果你发现自己不得不处理一个内核 +API,或者仅仅因为它不满足你的需求而不使用特定的功能,这可能是API需要改变的一 +个标志。作为内核开发人员,您有权进行此类更改。 + +当然, 可以进行API更改,但它们必须是合理的。因此,任何进行内部API更改的补丁都 +应该附带一个关于更改内容和必要原因的描述。这种变化也应该分解成一个单独的补丁, +而不是埋在一个更大的补丁中。 + +另一个要点是,更改内部API的开发人员通常要负责修复内核树中被更改破坏的任何代码。 +对于一个广泛使用的函数,这个职责可以导致成百上千的变化,其中许多变化可能与其他 +开发人员正在做的工作相冲突。不用说,这可能是一项大工作,所以最好确保理由是 +可靠的。请注意,coccinelle工具可以帮助进行广泛的API更改。 + +在进行不兼容的API更改时,应尽可能确保编译器捕获未更新的代码。这将帮助您确保找 +到该接口的树内用处。它还将警告开发人员树外代码存在他们需要响应的更改。支持树外 +代码不是内核开发人员需要担心的事情,但是我们也不必使树外开发人员的生活有不必要 +的困难。 diff --git a/Documentation/translations/zh_CN/process/5.Posting.rst b/Documentation/translations/zh_CN/process/5.Posting.rst new file mode 100644 index 000000000000..41aba21ff050 --- /dev/null +++ b/Documentation/translations/zh_CN/process/5.Posting.rst @@ -0,0 +1,240 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_posting: + +发送补丁 +======== + +迟早,当您的工作准备好提交给社区进行审查,并最终包含到主线内核中时。不出所料, +内核开发社区已经发展出一套用于发布补丁的约定和过程;遵循这些约定和过程将使 +参与其中的每个人的生活更加轻松。本文件将试图合理详细地涵盖这些期望;更多信息 +也可在以下文件中找到 +:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>`, +:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>` +和 :ref:`Documentation/translations/zh_CN/process/submit-checklist.rst <cn_submitchecklist>`. + +何时邮寄 +-------- + +在补丁完全“准备好”之前,有一个不断的诱惑来避免发布补丁。对于简单的补丁, +这不是问题。但是,如果正在完成的工作很复杂,那么在工作完成之前从社区获得 +反馈就可以获得很多好处。因此,您应该考虑发布正在进行的工作,甚至使Git树 +可用,以便感兴趣的开发人员可以随时赶上您的工作。 + +当发布还没有准备好包含的代码时,最好在发布本身中这样说。还应提及任何有待完成 +的主要工作和任何已知问题。很少有人会看到那些被认为是半生不熟的补丁,但是那些 +人会想到他们可以帮助你把工作推向正确的方向。 + +创建补丁之前 +------------ + +在考虑将补丁发送到开发社区之前,有许多事情应该做。这些包括: + + - 尽可能地测试代码。利用内核的调试工具,确保内核使用所有合理的配置选项组合 + 进行构建,使用跨编译器为不同的体系结构进行构建等。 + + - 确保您的代码符合内核编码风格指南。 + + - 您的更改是否具有性能影响?如果是这样,您应该运行基准测试来显示您的变更的 + 影响(或好处);结果的摘要应该包含在补丁中。 + + - 确保您有权发布代码。如果这项工作是为雇主完成的,雇主对这项工作具有所有权, + 并且必须同意根据GPL对其进行放行。 + +一般来说,在发布代码之前进行一些额外的思考,几乎总是能在短时间内得到回报。 + +补丁准备 +-------- + +准备发布补丁可能是一个惊人的工作量,但再次尝试节省时间在这里通常是不明智的, +即使在短期内。 + +必须针对内核的特定版本准备补丁。作为一般规则,补丁程序应该基于Linus的Git树中 +的当前主线。当以主线为基础时,从一个众所周知的发布点开始——一个稳定的或RC的 +发布——而不是在一个主线分支任意点。 + +但是,可能需要针对-mm、linux-next或子系统树生成版本,以便于更广泛的测试和审查。 +根据补丁的区域以及其他地方的情况,针对这些其他树建立补丁可能需要大量的工作来 +解决冲突和处理API更改。 + +只有最简单的更改才应格式化为单个补丁;其他所有更改都应作为一系列逻辑更改进行。 +分割补丁是一门艺术;一些开发人员花了很长时间来弄清楚如何按照社区期望的方式来 +做。然而,有一些经验法则可以大大帮助: + + - 您发布的补丁程序系列几乎肯定不会是工作系统中的一系列更改。相反,您所做的 + 更改需要在最终形式中加以考虑,然后以有意义的方式进行拆分。开发人员对离散的、 + 自包含的更改感兴趣,而不是您获取这些更改的路径。 + + - 每个逻辑上独立的变更都应该格式化为单独的补丁。这些更改可以是小的(“向此 + 结构添加字段”)或大的(例如,添加一个重要的新驱动程序),但它们在概念上 + 应该是小的,并且可以接受一行描述。每个补丁都应该做一个特定的更改,可以单独 + 检查并验证它所做的事情。 + + - 作为重申上述准则的一种方法:不要在同一补丁中混合不同类型的更改。如果一个 + 补丁修复了一个关键的安全漏洞,重新排列了一些结构,并重新格式化了代码,那么 + 很有可能它会被忽略,而重要的修复将丢失。 + + - 每个补丁都应该产生一个内核,它可以正确地构建和运行;如果补丁系列在中间被 + 中断,那么结果应该仍然是一个工作的内核。补丁系列的部分应用是使用 + “git bisct”工具查找回归的一个常见场景;如果结果是一个损坏的内核,那么对于 + 那些从事追踪问题的高尚工作的开发人员和用户来说,将使他们的生活更加艰难。 + + - 不过,不要过分。一位开发人员曾经将一组编辑内容作为500个单独的补丁发布到一个 + 文件中,这并没有使他成为内核邮件列表中最受欢迎的人。一个补丁可以相当大, + 只要它仍然包含一个单一的逻辑变更。 + + - 用一系列补丁添加一个全新的基础设施是很有诱惑力的,但是在系列中的最后一个 + 补丁启用整个补丁之前,该基础设施是不使用的。如果可能的话,应该避免这种 + 诱惑;如果这个系列增加了回归,那么二分法将指出最后一个补丁是导致问题的 + 补丁,即使真正的bug在其他地方。只要有可能,添加新代码的补丁程序应该立即 + 激活该代码。 + +创建完美补丁系列的工作可能是一个令人沮丧的过程,在完成“真正的工作”之后需要花费 +大量的时间和思考。但是,如果做得好,这是一段很好的时间。 + +补丁格式和更改日志 +------------------ + +所以现在你有了一系列完美的补丁可以发布,但是这项工作还没有完成。每个补丁都 +需要被格式化成一条消息,它可以快速而清晰地将其目的传达给世界其他地方。为此, +每个补丁将由以下部分组成: + + - 命名补丁作者的可选“from”行。只有当你通过电子邮件传递别人的补丁时,这一行 + 才是必要的,但是如果有疑问,添加它不会有任何伤害。 + + - 一行描述补丁的作用。对于没有其他上下文的读者来说,此消息应该足够了解补丁 + 的范围;这是将在“短格式”变更日志中显示的行。此消息通常首先用相关的子系统 + 名称格式化,然后是补丁的目的。例如: + + :: + + gpio: fix build on CONFIG_GPIO_SYSFS=n + + - 一个空白行,后面是补丁内容的详细描述。这个描述可以是必需的;它应该说明补丁 + 的作用以及为什么它应该应用于内核。 + + - 一个或多个标记行,至少有一个由补丁作者的:signed-off-by 签名。签名将在下面 + 更详细地描述。 + +上面的项目一起构成补丁的变更日志。写一篇好的变更日志是一门至关重要但常常被 +忽视的艺术;值得花一点时间来讨论这个问题。当你写一个变更日志时,你应该记住 +有很多不同的人会读你的话。其中包括子系统维护人员和审查人员,他们需要决定是否 +应该包括补丁,分销商和其他维护人员试图决定是否应该将补丁反向移植到其他内核, +bug搜寻人员想知道补丁是否负责他们正在追查的问题,想知道内核如何变化的用户。 +等等。一个好的变更日志以最直接和最简洁的方式向所有这些人传达所需的信息。 + +为此,总结行应该描述变更的影响和动机,以及在一行约束条件下可能发生的变化。 +然后,详细的描述可以详述这些主题,并提供任何需要的附加信息。如果补丁修复了 +一个bug,请引用引入该bug的commit(如果可能,请在引用commits时同时提供commit id +和标题)。如果某个问题与特定的日志或编译器输出相关联,请包含该输出以帮助其他 +人搜索同一问题的解决方案。如果更改是为了支持以后补丁中的其他更改,那么就这么 +说。如果更改了内部API,请详细说明这些更改以及其他开发人员应该如何响应。一般 +来说,你越能把自己放在每个阅读你的changelog的人的位置上,changelog(和内核 +作为一个整体)就越好。 + +不用说,变更日志应该是将变更提交到修订控制系统时使用的文本。接下来是: + + - 补丁本身,采用统一的(“-u”)补丁格式。将“-p”选项用于diff将使函数名与更改 + 相关联,从而使结果补丁更容易被其他人读取。 + +您应该避免在补丁中包括对不相关文件(例如,由构建过程生成的文件或编辑器 +备份文件)的更改。文档目录中的文件“dontdiff”在这方面有帮助;使用“-X”选项将 +其传递给diff。 + +上面提到的标签用于描述各种开发人员如何与这个补丁的开发相关联。 +:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` +文档中对它们进行了详细描述;下面是一个简短的总结。每一行的格式如下: + +:: + + tag: Full Name <email address> optional-other-stuff + +常用的标签有: + + - Signed-off-by: 这是一个开发人员的证明,他或她有权提交补丁以包含到内核中。 + 这是开发来源认证协议,其全文可在 + :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` + 中找到,如果没有适当的签字,则不能合并到主线中。 + + - Co-developed-by: 声明补丁是由多个开发人员共同创建的;当几个人在一个补丁上 + 工作时,它用于将属性赋予共同作者(除了 From: 所赋予的作者之外)。因为 + Co-developed-by: 表示作者身份,所以每个共同开发人, 必须紧跟在相关合作作者 + 的签名之后。具体内容和示例可以在以下文件中找到 + :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` + + - Acked-by: 表示另一个开发人员(通常是相关代码的维护人员)同意补丁适合包含 + 在内核中。 + + - Tested-by: 声明指定的人已经测试了补丁并发现它可以工作。 + + - Reviewed-by: 指定的开发人员已经审查了补丁的正确性;有关详细信息,请参阅 + :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` + + - Reported-by: 指定报告此补丁修复的问题的用户;此标记用于提供感谢。 + + - Cc:指定的人收到了补丁的副本,并有机会对此发表评论。 + +在补丁中添加标签时要小心:只有cc:才适合在没有指定人员明确许可的情况下添加。 + +发送补丁 +-------- + +在邮寄补丁之前,您还需要注意以下几点: + + - 您确定您的邮件发送程序不会损坏补丁吗?有免费的空白更改或由邮件客户端 + 执行的行包装的补丁不会在另一端复原,并且通常不会进行任何详细检查。如果有 + 任何疑问,把补丁寄给你自己,让你自己相信它是完好无损的。 + + :ref:`Documentation/translations/zh_CN/process/email-clients.rst <cn_email_clients>` + 提供了一些有用的提示,可以让特定的邮件客户机工作以发送补丁。 + + - 你确定你的补丁没有愚蠢的错误吗?您应该始终通过scripts/checkpatch.pl运行 + 补丁程序,并解决它提出的投诉。请记住,checkpatch.pl虽然是大量思考内核 + 补丁应该是什么样子的体现,但它并不比您聪明。如果修复checkpatch.pl投诉会 + 使代码变得更糟,请不要这样做。 + +补丁应始终以纯文本形式发送。请不要将它们作为附件发送;这使得审阅者在答复中更难 +引用补丁的部分。相反,只需将补丁直接放到您的消息中。 + +邮寄补丁时,重要的是将副本发送给任何可能感兴趣的人。与其他一些项目不同,内核 +鼓励人们错误地发送过多的副本;不要假定相关人员会看到您在邮件列表中的发布。 +尤其是,副本应发送至: + + - 受影响子系统的维护人员。如前所述,维护人员文件是查找这些人员的第一个地方。 + + - 其他在同一领域工作的开发人员,尤其是那些现在可能在那里工作的开发人员。使用 + git查看还有谁修改了您正在处理的文件,这很有帮助。 + + - 如果您对错误报告或功能请求做出响应,也可以抄送原始发送人。 + + - 将副本发送到相关邮件列表,或者,如果没有其他应用,则发送到Linux内核列表。 + + - 如果您正在修复一个bug,请考虑该修复是否应进入下一个稳定更新。如果是这样, + stable@vger.kernel.org 应该得到补丁的副本。另外,在补丁本身的标签中添加 + 一个“cc:stable@vger.kernel.org”;这将使稳定团队在修复进入主线时收到通知。 + +当为一个补丁选择接收者时,最好知道你认为谁最终会接受这个补丁并将其合并。虽然 +可以将补丁直接发送给LinusTorvalds并让他合并,但通常情况下不会这样做。Linus +很忙,并且有子系统维护人员负责监视内核的特定部分。通常您会希望维护人员合并您 +的补丁。如果没有明显的维护人员,Andrew Morton通常是最后的补丁目标。 + +补丁需要好的主题行。补丁程序行的规范格式如下: + +:: + + [PATCH nn/mm] subsys: one-line description of the patch + +其中“nn”是补丁的序号,“mm”是系列中补丁的总数,“subsys”是受影响子系统的名称。 +显然,一个单独的补丁可以省略nn/mm。 + +如果您有一系列重要的补丁,那么通常将介绍性描述作为零部分发送。不过,这种约定 +并没有得到普遍遵循;如果您使用它,请记住简介中的信息不会使它进入内核变更日志。 +因此,请确保补丁本身具有完整的变更日志信息。 + +一般来说,多部分补丁的第二部分和后续部分应作为对第一部分的回复发送,以便它们 +在接收端都连接在一起。像git和coilt这样的工具有命令,可以通过适当的线程发送 +一组补丁。但是,如果您有一个长系列,并且正在使用git,请远离–chain reply-to +选项,以避免创建异常深的嵌套。 diff --git a/Documentation/translations/zh_CN/process/6.Followthrough.rst b/Documentation/translations/zh_CN/process/6.Followthrough.rst new file mode 100644 index 000000000000..f509e077e1cb --- /dev/null +++ b/Documentation/translations/zh_CN/process/6.Followthrough.rst @@ -0,0 +1,145 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_followthrough: + +跟进 +==== + +在这一点上,您已经遵循了到目前为止给出的指导方针,并且,随着您自己的工程技能 +的增加,已经发布了一系列完美的补丁。即使是经验丰富的内核开发人员也能犯的最大 +错误之一是,认为他们的工作现在已经完成了。事实上,发布补丁意味着进入流程的下 +一个阶段,可能还需要做很多工作。 + +一个补丁在第一次发布时就非常出色,没有改进的余地,这是很罕见的。内核开发流程 +认识到这一事实,因此,它非常注重对已发布代码的改进。作为代码的作者,您应该与 +内核社区合作,以确保您的代码符合内核的质量标准。如果不参与这个过程,很可能会 +阻止将补丁包含到主线中。 + +与审阅者合作 +------------ + +任何意义上的补丁都会导致其他开发人员在审查代码时发表大量评论。对于许多开发 +人员来说,与审查人员合作可能是内核开发过程中最令人生畏的部分。但是,如果你 +记住一些事情,生活会变得容易得多: + + - 如果你已经很好地解释了你的补丁,评论人员会理解它的价值,以及为什么你会 + 费尽心思去写它。但是这个并不能阻止他们提出一个基本的问题:五年或十年后 + 用这个代码维护一个内核会是什么感觉?你可能被要求做出的许多改变——从编码风格 + 的调整到大量的重写——都来自于对Linux的理解,即从现在起十年后,Linux仍将在 + 开发中。 + + - 代码审查是一项艰苦的工作,这是一项相对吃力不讨好的工作;人们记得谁编写了 + 内核代码,但对于那些审查它的人来说,几乎没有什么持久的名声。因此,评论 + 人员可能会变得暴躁,尤其是当他们看到同样的错误被一遍又一遍地犯下时。如果 + 你得到了一个看起来愤怒、侮辱或完全冒犯你的评论,抵制以同样方式回应的冲动。 + 代码审查是关于代码的,而不是关于人的,代码审查人员不会亲自攻击您。 + + - 同样,代码审查人员也不想以牺牲你雇主的利益为代价来宣传他们雇主的议程。 + 内核开发人员通常希望今后几年能在内核上工作,但他们明白他们的雇主可能会改 + 变。他们真的,几乎毫无例外地,致力于创造他们所能做到的最好的内核;他们并 + 没有试图给雇主的竞争对手造成不适。 + +所有这些归根结底都是,当审阅者向您发送评论时,您需要注意他们正在进行的技术 +观察。不要让他们的表达方式或你自己的骄傲阻止这种事情的发生。当你在一个补丁 +上得到评论时,花点时间去理解评论人想说什么。如果可能的话,请修复审阅者要求 +您修复的内容。然后回复审稿人:谢谢他们,并描述你将如何回答他们的问题。 + +请注意,您不必同意审阅者建议的每个更改。如果您认为审阅者误解了您的代码,请 +解释到底发生了什么。如果您对建议的更改有技术上的异议,请描述它并证明您对该 +问题的解决方案是正确的。如果你的解释有道理,审稿人会接受的。不过,如果你的 +解释不能证明是有说服力的,尤其是当其他人开始同意审稿人的观点时,请花些时间 +重新考虑一下。你很容易对自己解决问题的方法视而不见,以至于你没有意识到某个 +问题根本是错误的,或者你甚至没有解决正确的问题。 + +Andrew Morton建议,每一条不会导致代码更改的评论都应该导致额外的代码注释; +这可以帮助未来的评论人员避免出现第一次出现的问题。 + +一个致命的错误是忽视评论,希望它们会消失。他们不会走的。如果您在没有对之前 +收到的注释做出响应的情况下重新发布代码,那么很可能会发现补丁毫无用处。 + +说到重新发布代码:请记住,审阅者不会记住您上次发布的代码的所有细节。因此, +提醒审查人员以前提出的问题以及您如何处理这些问题总是一个好主意;补丁变更 +日志是提供此类信息的好地方。审阅者不必搜索列表档案来熟悉上次所说的内容; +如果您帮助他们开始运行,当他们重新访问您的代码时,他们的心情会更好。 + +如果你已经试着做正确的事情,但事情仍然没有进展呢?大多数技术上的分歧都可以 +通过讨论来解决,但有时人们只需要做出决定。如果你真的认为这个决定对你不利, +你可以试着向更高的权力上诉。在这篇文章中,更高的权力倾向于Andrew Morton。 +Andrew在内核开发社区中受i很大的尊重;他经常为似乎被绝望地阻塞事情清障。 +尽管如此,对Andrew的呼吁不应轻而易举,也不应在所有其他替代方案都被探索之前 +使用。当然,记住,他也可能不同意你的意见。 + +接下来会发生什么 +---------------- + +如果一个补丁被认为是添加到内核中的一件好事,并且一旦大多数审查问题得到解决, +下一步通常是进入子系统维护人员的树中。工作方式因子系统而异;每个维护人员都 +有自己的工作方式。特别是,可能有不止一棵树——一棵树,也许,专门用于计划下一 +个合并窗口的补丁,另一棵树用于长期工作。 + +对于应用于没有明显子系统树(例如内存管理修补程序)的区域的修补程序,默认树 +通常以-mm结尾。影响多个子系统的补丁也可以最终通过-mm树。 + +包含在子系统树中可以提高补丁的可见性。现在,使用该树的其他开发人员将默认获 +得补丁。子系统树通常也为Linux提供支持,使其内容对整个开发社区可见。在这一点 +上,您很可能会从一组新的审阅者那里得到更多的评论;这些评论需要像上一轮那样 +得到回答。 + +在这一点上也会发生什么,这取决于你的补丁的性质,是与其他人正在做的工作发生 +冲突。在最坏的情况下,严重的补丁冲突可能会导致一些工作被搁置,以便剩余的补丁 +可以成形并合并。另一些时候,冲突解决将涉及到与其他开发人员合作,可能还会 +在树之间移动一些补丁,以确保所有的应用都是干净的。这项工作可能是一件痛苦的 +事情,但要计算您的福祉:在Linux下一棵树出现之前,这些冲突通常只在合并窗口 +中出现,必须迅速解决。现在可以在合并窗口打开之前,在空闲时解决这些问题。 + +有朝一日,如果一切顺利,您将登录并看到您的补丁已经合并到主线内核中。祝贺你! +然而,一旦庆祝活动完成(并且您已经将自己添加到维护人员文件中),就值得记住 +一个重要的小事实:工作仍然没有完成。并入主线带来了自身的挑战。 + +首先,补丁的可见性再次提高。可能会有新一轮的开发者评论,他们以前不知道这 +个补丁。忽略它们可能很有诱惑力,因为您的代码不再存在任何被合并的问题。但是, +要抵制这种诱惑,您仍然需要对有问题或建议的开发人员作出响应。 + +不过,更重要的是:将代码包含在主线中会将代码交给更大的一组测试人员。即使您 +为尚未提供的硬件提供了驱动程序,您也会惊讶于有多少人会将您的代码构建到内核 +中。当然,如果有测试人员,也会有错误报告。 + +最糟糕的错误报告是回归。如果你的补丁导致回归,你会发现很多不舒服的眼睛盯着 +你;回归需要尽快修复。如果您不愿意或无法修复回归(其他人都不会为您修复), +那么在稳定期内,您的补丁几乎肯定会被移除。除了否定您为使补丁进入主线所做的 +所有工作之外,如果由于未能修复回归而取消补丁,很可能会使将来的工作更难合并。 + +在处理完任何回归之后,可能还有其他普通的bug需要处理。稳定期是修复这些错误并 +确保代码在主线内核版本中的首次发布尽可能可靠的最好机会。所以,请回答错误 +报告,并尽可能解决问题。这就是稳定期的目的;一旦解决了旧补丁的任何问题,就 +可以开始创建酷的新补丁。 + +别忘了,还有其他里程碑也可能会创建bug报告:下一个主线稳定版本,当著名的发行 +商选择包含补丁的内核版本时,等等。继续响应这些报告是您工作的基本骄傲。但是, +如果这不是足够的动机,那么也值得考虑的是,开发社区会记住那些在合并后对代码 +失去兴趣的开发人员。下一次你发布补丁时,他们会以你以后不会在身边维护它为假 +设来评估它。 + +其他可能发生的事情 +------------------ + +有一天,你可以打开你的邮件客户端,看到有人给你寄了一个代码补丁。毕竟,这是 +让您的代码公开存在的好处之一。如果您同意这个补丁,您可以将它转发给子系统 +维护人员(确保包含一个正确的From:行,这样属性是正确的,并添加一个您自己 +的签准),或者回复一个Acked-by,让原始发送者向上发送它。 + +如果您不同意补丁,请发送一个礼貌的回复,解释原因。如果可能的话,告诉作者需要 +做哪些更改才能让您接受补丁。对于代码的编写者和维护者所反对的合并补丁,存在着 +一定的阻力,但仅此而已。如果你被认为不必要的阻碍了好的工作,那么这些补丁最 +终会经过你身边并进入主线。在Linux内核中,没有人对任何代码拥有绝对的否决权。 +除了Linus。 + +在非常罕见的情况下,您可能会看到完全不同的东西:另一个开发人员发布了针对您 +的问题的不同解决方案。在这一点上,两个补丁中的一个可能不会合并,“我的在这里 +是第一个”不被认为是一个令人信服的技术论据。如果有人的补丁取代了你的补丁而进 +入了主线,那么只有一种方法可以回应你:高兴你的问题得到解决,继续你的工作。 +以这种方式把一个人的工作推到一边可能会伤害和气馁,但是在他们忘记了谁的补丁 +真正被合并很久之后,社区会记住你的反应。 diff --git a/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst b/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst new file mode 100644 index 000000000000..956815edbd18 --- /dev/null +++ b/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst @@ -0,0 +1,124 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_advancedtopics: + +高级主题 +======== + +现在,希望您能够掌握开发流程的工作方式。然而,还有更多的东西要学!本节将介绍 +一些主题,这些主题对希望成为Linux内核开发过程常规部分的开发人员有帮助。 + +使用Git管理补丁 +--------------- + +内核使用分布式版本控制始于2002年初,当时Linus首次开始使用专有的Bitkeeper应用 +程序。虽然bitkeeper存在争议,但它所体现的软件版本管理方法却肯定不是。分布式 +版本控制可以立即加速内核开发项目。在当前的时代,有几种免费的比特保持器替代品。 +无论好坏,内核项目都将Git作为其选择的工具。 + +使用Git管理补丁可以使开发人员的生活更加轻松,尤其是随着补丁数量的增加。Git +也有其粗糙的边缘和一定的危险,它是一个年轻和强大的工具,仍然在其开发人员完善 +中。本文档不会试图教会读者如何使用git;这会是个巨长的文档。相反,这里的重点 +将是Git如何特别适合内核开发过程。想要加快Git的开发人员可以在以下网站上找到 +更多信息: + + http://git-scm.com/ + + http://www.kernel.org/pub/software/scm/git/docs/user-manual.html + +在尝试使用它使补丁可供其他人使用之前,第一要务是阅读上述站点,对Git的工作 +方式有一个扎实的了解。使用Git的开发人员应该能够获得主线存储库的副本,探索 +修订历史,提交对树的更改,使用分支等。了解Git用于重写历史的工具(如Rebase) +也很有用。Git有自己的术语和概念;Git的新用户应该了解refs、远程分支、索引、 +快进合并、推拉、分离头等。一开始可能有点吓人,但这些概念不难通过一点学习来 +理解。 + +使用git生成通过电子邮件提交的补丁是提高速度的一个很好的练习。 + +当您准备好开始安装Git树供其他人查看时,您当然需要一个可以从中提取的服务器。 +如果您有一个可以访问Internet的系统,那么使用git守护进程设置这样的服务器相 +对简单。否则,免费的公共托管网站(例如github)开始出现在网络上。成熟的开发 +人员可以在kernel.org上获得一个帐户,但这些帐户并不容易找到;有关更多信息, +请参阅 http://kernel.org/faq/ + +正常的Git工作流程涉及到许多分支的使用。每一条开发线都可以分为单独的“主题 +分支”,并独立维护。Git的分支机构很便宜,没有理由不免费使用它们。而且,在 +任何情况下,您都不应该在任何您打算让其他人从中受益的分支中进行开发。应该 +小心地创建公开可用的分支;当它们处于完整的形式并准备好运行时(而不是之前), +合并开发分支的补丁。 + +Git提供了一些强大的工具,可以让您重写开发历史。一个不方便的补丁(比如说, +一个打破二分法的补丁,或者有其他一些明显的缺陷)可以在适当的位置修复,或者 +完全从历史中消失。一个补丁系列可以被重写,就好像它是在今天的主线之上写的 +一样,即使你已经花了几个月的时间在写它。可以透明地将更改从一个分支转移到另 +一个分支。等等。明智地使用git修改历史的能力可以帮助创建问题更少的干净补丁集。 + +然而,过度使用这种能力可能会导致其他问题,而不仅仅是对创建完美项目历史的 +简单痴迷。重写历史将重写该历史中包含的更改,将经过测试(希望)的内核树变 +为未经测试的内核树。但是,除此之外,如果开发人员没有对项目历史的共享视图, +他们就无法轻松地协作;如果您重写了其他开发人员拉入他们存储库的历史,您将 +使这些开发人员的生活更加困难。因此,这里有一个简单的经验法则:被导出到其他 +人的历史在此后通常被认为是不可变的。 + +因此,一旦将一组更改推送到公开可用的服务器上,就不应该重写这些更改。如果您 +尝试强制进行不会导致快进合并(即不共享同一历史记录的更改)的更改,Git将尝 +试强制执行此规则。可以重写此检查,有时可能需要重写导出的树。在树之间移动变 +更集以避免Linux-next中的冲突就是一个例子。但这种行为应该是罕见的。这就是为 +什么开发应该在私有分支中进行(必要时可以重写)并且只有在公共分支处于合理的 +高级状态时才转移到公共分支中的原因之一。 + +当主线(或其他一组变更所基于的树)前进时,很容易与该树合并以保持领先地位。 +对于一个私有的分支,rebasing 可能是一个很容易跟上另一棵树的方法,但是一旦 +一棵树被导出到全世界,rebasing就不是一个选项。一旦发生这种情况,就必须进行 +完全合并(merge)。合并有时是很有意义的,但是过于频繁的合并会不必要地扰乱 +历史。在这种情况下,建议的技术是不经常合并,通常只在特定的发布点(如主线-rc +发布)合并。如果您对特定的更改感到紧张,则可以始终在私有分支中执行测试合并。 +在这种情况下,git rerere 工具很有用;它记住合并冲突是如何解决的,这样您就 +不必重复相同的工作。 + +关于Git这样的工具的一个最大的反复抱怨是:补丁从一个存储库到另一个存储库的 +大量移动使得很容易陷入错误建议的变更中,这些变更避开审查雷达进入主线。当内 +核开发人员看到这种情况发生时,他们往往会感到不高兴;在Git树上放置未查看或 +主题外的补丁可能会影响您将来获取树的能力。引用Linus: + +:: + + 你可以给我发补丁,但要我从你哪里取一个Git补丁,我需要知道你知道 + 你在做什么,我需要能够相信事情而不去检查每个个人改变。 + +(http://lwn.net/articles/224135/)。 + +为了避免这种情况,请确保给定分支中的所有补丁都与相关主题紧密相关;“驱动程序 +修复”分支不应更改核心内存管理代码。而且,最重要的是,不要使用Git树来绕过 +审查过程。不时的将树的摘要发布到相关的列表中,当时间合适时,请求 +Linux-next 中包含该树。 + +如果其他人开始发送补丁以包含到您的树中,不要忘记查看它们。还要确保您维护正确 +的作者信息; ``git am`` 工具在这方面做得最好,但是如果它通过第三方转发给您, +您可能需要在补丁中添加“From:”行。 + +请求pull操作时,请务必提供所有相关信息:树的位置、要拉的分支以及拉操作将导致 +的更改。在这方面,git request pull 命令非常有用;它将按照其他开发人员的预期 +格式化请求,并检查以确保您记住了将这些更改推送到公共服务器。 + +审查补丁 +-------- + +一些读者当然会反对将本节与“高级主题”放在一起,因为即使是刚开始的内核开发人员 +也应该检查补丁。当然,学习如何在内核环境中编程没有比查看其他人发布的代码更好 +的方法了。此外,审阅者永远供不应求;通过查看代码,您可以对整个流程做出重大贡献。 + +审查代码可能是一个令人生畏的前景,特别是对于一个新的内核开发人员来说,他们 +可能会对公开询问代码感到紧张,而这些代码是由那些有更多经验的人发布的。不过, +即使是最有经验的开发人员编写的代码也可以得到改进。也许对评审员(所有评审员) +最好的建议是:把评审评论当成问题而不是批评。询问“在这条路径中如何释放锁?” +总是比说“这里的锁是错误的”更好。 + +不同的开发人员将从不同的角度审查代码。一些主要关注的是编码样式以及代码行是 +否有尾随空格。其他人将主要关注补丁作为一个整体实现的变更是否对内核有好处。 +然而,其他人会检查是否存在锁定问题、堆栈使用过度、可能的安全问题、在其他 +地方发现的代码重复、足够的文档、对性能的不利影响、用户空间ABI更改等。所有 +类型的检查,如果它们导致更好的代码进入内核,都是受欢迎和值得的。 diff --git a/Documentation/translations/zh_CN/process/8.Conclusion.rst b/Documentation/translations/zh_CN/process/8.Conclusion.rst new file mode 100644 index 000000000000..2bbd76161e10 --- /dev/null +++ b/Documentation/translations/zh_CN/process/8.Conclusion.rst @@ -0,0 +1,64 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_conclusion: + +更多信息 +======== + +关于Linux内核开发和相关主题的信息来源很多。首先是在内核源代码分发中找到的 +文档目录。顶级 :ref:`Documentation/translations/zh_CN/process/howto.rst <cn_process_howto>` +文件是一个重要的起点 +:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` +和 :ref:`process/submitting-drivers.rst <submittingdrivers>` +也是所有内核开发人员都应该阅读的内容。许多内部内核API都是使用kerneldoc机制 +记录的;“make htmldocs”或“make pdfdocs”可用于以HTML或PDF格式生成这些文档( +尽管某些发行版提供的tex版本会遇到内部限制,无法正确处理文档)。 + +不同的网站在各个细节层次上讨论内核开发。您的作者想谦虚地建议用 http://lwn.net/ +作为来源;有关许多特定内核主题的信息可以通过以下网址的lwn内核索引找到: + + http://lwn.net/kernel/index/ + +除此之外,内核开发人员的一个宝贵资源是: + + http://kernelnewbies.org/ + +当然,我们不应该忘记 http://kernel.org/ 这是内核发布信息的最终位置。 + +关于内核开发有很多书: + + Linux设备驱动程序,第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman)。 + 在线:http://lwn.net/kernel/ldd3/ + + Linux内核开发(Robert Love)。 + + 了解Linux内核(Daniel Bovet和Marco Cesati)。 + +然而,所有这些书都有一个共同的缺点:当它们上架时,它们往往有些过时,而且它们 +已经上架一段时间了。不过,在那里还可以找到相当多的好信息。 + +有关git的文档,请访问: + + http://www.kernel.org/pub/software/scm/git/docs/ + + http://www.kernel.org/pub/software/scm/git/docs/user-manual.html + +结论 +==== + +祝贺所有通过这篇冗长的文件的人。希望它能够帮助您理解Linux内核是如何开发的, +以及您如何参与这个过程。 + +最后,重要的是参与。任何开源软件项目都不超过其贡献者投入其中的总和。Linux内核 +的发展速度和以前一样快,因为它得到了大量开发人员的帮助,他们都在努力使它变得 +更好。内核是一个主要的例子,说明当成千上万的人为了一个共同的目标一起工作时, +可以做些什么。 + +不过,内核总是可以从更大的开发人员基础中获益。总有更多的工作要做。但是,同样 +重要的是,Linux生态系统中的大多数其他参与者可以通过为内核做出贡献而受益。使 +代码进入主线是提高代码质量、降低维护和分发成本、提高对内核开发方向的影响程度 +等的关键。这是一种人人都赢的局面。踢开你的编辑,来加入我们吧,你会非常受 +欢迎的。 diff --git a/Documentation/translations/zh_CN/process/code-of-conduct-interpretation.rst b/Documentation/translations/zh_CN/process/code-of-conduct-interpretation.rst new file mode 100644 index 000000000000..c323ce76e0cb --- /dev/null +++ b/Documentation/translations/zh_CN/process/code-of-conduct-interpretation.rst @@ -0,0 +1,108 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/code-of-conduct-interpretation.rst <code_of_conduct_interpretation>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_code_of_conduct_interpretation: + +Linux内核贡献者契约行为准则解释 +=============================== + +:ref:`cn_code_of_conduct` 准则是一个通用文档,旨在为几乎所有开源社区提供一套规则。 +每个开源社区都是独一无二的,Linux内核也不例外。因此,本文描述了Linux内核社区中 +如何解释它。我们也不希望这种解释随着时间的推移是静态的,并将根据需要进行调整。 + +与开发软件的“传统”方法相比,Linux内核开发工作是一个非常个人化的过程。你的贡献 +和背后的想法将被仔细审查,往往导致批判和批评。审查将几乎总是需要改进,材料才 +能包括在内核中。要知道这是因为所有相关人员都希望看到Linux整体成功的最佳解决方 +案。这个开发过程已经被证明可以创建有史以来最健壮的操作系统内核,我们不想做任何 +事情来导致提交质量和最终结果的下降。 + +维护者 +------ + +行为准则多次使用“维护者”一词。在内核社区中,“维护者”是负责子系统、驱动程序或 +文件的任何人,并在内核源代码树的维护者文件中列出。 + +责任 +---- + +《行为准则》提到了维护人员的权利和责任,这需要进一步澄清。 + +首先,最重要的是,有一个合理的期望是由维护人员通过实例来领导。 + +也就是说,我们的社区是广阔的,对维护者没有新的要求,他们单方面处理其他人在 +他们活跃的社区的行为。这一责任由我们所有人承担,最终《行为准则》记录了最终的 +上诉路径,以防有关行为问题的问题悬而未决。 + +维护人员应该愿意在出现问题时提供帮助,并在需要时与社区中的其他人合作。如果您 +不确定如何处理出现的情况,请不要害怕联系技术咨询委员会(TAB)或其他维护人员。 +除非您愿意,否则不会将其视为违规报告。如果您不确定是否该联系TAB 或任何其他维 +护人员,请联系我们的冲突调解人 Mishi Choudhary <mishi@linux.com>。 + +最后,“善待对方”才是每个人的最终目标。我们知道每个人都是人,有时我们都会失败, +但我们所有人的首要目标应该是努力友好地解决问题。执行行为准则将是最后的选择。 + +我们的目标是创建一个强大的、技术先进的操作系统,以及所涉及的技术复杂性,这自 +然需要专业知识和决策。 + +所需的专业知识因贡献领域而异。它主要由上下文和技术复杂性决定,其次由贡献者和 +维护者的期望决定。 + +专家的期望和决策都要经过讨论,但在最后,为了取得进展,必须能够做出决策。这一 +特权掌握在维护人员和项目领导的手中,预计将善意使用。 + +因此,设定专业知识期望、作出决定和拒绝不适当的贡献不被视为违反行为准则。 + +虽然维护人员一般都欢迎新来者,但他们帮助(新)贡献者克服障碍的能力有限,因此 +他们必须确定优先事项。这也不应被视为违反了行为准则。内核社区意识到这一点,并 +以各种形式提供入门级节目,如 kernelnewbies.org 。 + +范围 +---- + +Linux内核社区主要在一组公共电子邮件列表上进行交互,这些列表分布在由多个不同 +公司或个人控制的多个不同服务器上。所有这些列表都在内核源代码树中的 +MAINTAINERS 文件中定义。发送到这些邮件列表的任何电子邮件都被视为包含在行为 +准则中。 + +使用 kernel.org bugzilla和其他子系统bugzilla 或bug跟踪工具的开发人员应该遵循 +行为准则的指导原则。Linux内核社区没有“官方”项目电子邮件地址或“官方”社交媒体 +地址。使用kernel.org电子邮件帐户执行的任何活动必须遵循为kernel.org发布的行为 +准则,就像任何使用公司电子邮件帐户的个人必须遵循该公司的特定规则一样。 + +行为准则并不禁止在邮件列表消息、内核更改日志消息或代码注释中继续包含名称、 +电子邮件地址和相关注释。 + +其他论坛中的互动包括在适用于上述论坛的任何规则中,通常不包括在行为准则中。 +除了在极端情况下可考虑的例外情况。 + +提交给内核的贡献应该使用适当的语言。在行为准则之前已经存在的内容现在不会被 +视为违反。然而,不适当的语言可以被视为一个bug;如果任何相关方提交补丁, +这样的bug将被更快地修复。当前属于用户/内核API的一部分的表达式,或者反映已 +发布标准或规范中使用的术语的表达式,不被视为bug。 + +执行 +---- + +行为准则中列出的地址属于行为准则委员会。https://kernel.org/code-of-conduct.html +列出了在任何给定时间接收这些电子邮件的确切成员。成员不能访问在加入委员会之前 +或离开委员会之后所做的报告。 + +最初的行为准则委员会由TAB的志愿者以及作为中立第三方的专业调解人组成。委员会 +的首要任务是建立文件化的流程,并将其公开。 + +如果报告人不希望将整个委员会纳入投诉或关切,可直接联系委员会的任何成员,包括 +调解人。 + +行为准则委员会根据流程审查案例(见上文),并根据需要和适当与TAB协商,例如请求 +和接收有关内核社区的信息。 + +委员会做出的任何决定都将提交到表中,以便在必要时与相关维护人员一起执行。行为 +准则委员会的决定可以通过三分之二的投票推翻。 + +每季度,行为准则委员会和标签将提供一份报告,概述行为准则委员会收到的匿名报告 +及其状态,以及任何否决决定的细节,包括完整和可识别的投票细节。 + +我们希望在启动期之后为行为准则委员会人员配备建立一个不同的流程。发生此情况时, +将使用该信息更新此文档。 diff --git a/Documentation/translations/zh_CN/process/code-of-conduct.rst b/Documentation/translations/zh_CN/process/code-of-conduct.rst new file mode 100644 index 000000000000..99024df058e9 --- /dev/null +++ b/Documentation/translations/zh_CN/process/code-of-conduct.rst @@ -0,0 +1,72 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/code-of-conduct.rst <code_of_conduct>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_code_of_conduct: + +贡献者契约行为准则 +++++++++++++++++++ + +我们的誓言 +========== + +为了营造一个开放、友好的环境,我们作为贡献者和维护人承诺,让我们的社区和参 +与者,拥有一个无骚扰的体验,无论年龄、体型、残疾、种族、性别特征、性别认同 +和表达、经验水平、教育程度、社会状况,经济地位、国籍、个人外貌、种族、宗教 +或性身份和取向。 + +我们的标准 +========== + +有助于创造积极环境的行为包括: + +* 使用欢迎和包容的语言 +* 尊重不同的观点和经验 +* 优雅地接受建设性的批评 +* 关注什么对社区最有利 +* 对其他社区成员表示同情 + +参与者的不可接受行为包括: + +* 使用性意味的语言或意象以及不受欢迎的性注意或者更过分的行为 +* 煽动、侮辱/贬损评论以及个人或政治攻击 +* 公开或私下骚扰 +* 未经明确许可,发布他人的私人信息,如物理或电子地址。 +* 在专业场合被合理认为不适当的其他行为 + +我们的责任 +========== + +维护人员负责澄清可接受行为的标准,并应针对任何不可接受行为采取适当和公平的 +纠正措施。 + +维护人员有权和责任删除、编辑或拒绝与本行为准则不一致的评论、承诺、代码、 +wiki编辑、问题和其他贡献,或暂时或永久禁止任何贡献者从事他们认为不适当、 +威胁、冒犯或有害的其他行为。 + +范围 +==== + +当个人代表项目或其社区时,本行为准则既适用于项目空间,也适用于公共空间。 +代表一个项目或社区的例子包括使用一个正式的项目电子邮件地址,通过一个正式 +的社交媒体帐户发布,或者在在线或离线事件中担任指定的代表。项目维护人员可以 +进一步定义和澄清项目的表示。 + +执行 +==== + +如有滥用、骚扰或其他不可接受的行为,可联系行为准则委员会<conduct@kernel.org>。 +所有投诉都将接受审查和调查,并将得到必要和适当的答复。行为准则委员会有义务 +对事件报告人保密。具体执行政策的进一步细节可单独公布。 + +归属 +==== + +本行为准则改编自《贡献者契约》,版本1.4,可从 +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 获取。 + +解释 +==== + +有关Linux内核社区如何解释此文档,请参阅 :ref:`cn_code_of_conduct_interpretation` diff --git a/Documentation/translations/zh_CN/process/coding-style.rst b/Documentation/translations/zh_CN/process/coding-style.rst new file mode 100644 index 000000000000..5479c591c2f7 --- /dev/null +++ b/Documentation/translations/zh_CN/process/coding-style.rst @@ -0,0 +1,954 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/coding-style.rst <codingstyle>` + +.. _cn_codingstyle: + +译者:: + + 中文版维护者: 张乐 Zhang Le <r0bertz@gentoo.org> + 中文版翻译者: 张乐 Zhang Le <r0bertz@gentoo.org> + 中文版校译者: 王聪 Wang Cong <xiyou.wangcong@gmail.com> + wheelz <kernel.zeng@gmail.com> + 管旭东 Xudong Guan <xudong.guan@gmail.com> + Li Zefan <lizf@cn.fujitsu.com> + Wang Chen <wangchen@cn.fujitsu.com> + +Linux 内核代码风格 +========================= + +这是一个简短的文档,描述了 linux 内核的首选代码风格。代码风格是因人而异的, +而且我不愿意把自己的观点强加给任何人,但这就像我去做任何事情都必须遵循的原则 +那样,我也希望在绝大多数事上保持这种的态度。请 (在写代码时) 至少考虑一下这里 +的代码风格。 + +首先,我建议你打印一份 GNU 代码规范,然后不要读。烧了它,这是一个具有重大象征 +性意义的动作。 + +不管怎样,现在我们开始: + + +1) 缩进 +-------------- + +制表符是 8 个字符,所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4 (甚至 +2!) 字符深,这几乎相当于尝试将圆周率的值定义为 3。 + +理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的 +屏幕连续看了 20 小时之后,你将会发现大一点的缩进会使你更容易分辨缩进。 + +现在,有些人会抱怨 8 个字符的缩进会使代码向右边移动的太远,在 80 个字符的终端 +屏幕上就很难读这样的代码。这个问题的答案是,如果你需要 3 级以上的缩进,不管用 +何种方式你的代码已经有问题了,应该修正你的程序。 + +简而言之,8 个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太 +深的时候可以给你警告。留心这个警告。 + +在 switch 语句中消除多级缩进的首选的方式是让 ``switch`` 和从属于它的 ``case`` +标签对齐于同一列,而不要 ``两次缩进`` ``case`` 标签。比如: + +.. code-block:: c + + switch (suffix) { + case 'G': + case 'g': + mem <<= 30; + break; + case 'M': + case 'm': + mem <<= 20; + break; + case 'K': + case 'k': + mem <<= 10; + /* fall through */ + default: + break; + } + +不要把多个语句放在一行里,除非你有什么东西要隐藏: + +.. code-block:: c + + if (condition) do_this; + do_something_everytime; + +也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读 +的表达式。 + +除了注释、文档和 Kconfig 之外,不要使用空格来缩进,前面的例子是例外,是有意为 +之。 + +选用一个好的编辑器,不要在行尾留空格。 + + +2) 把长的行和字符串打散 +------------------------------ + +代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。 + +每一行的长度的限制是 80 列,我们强烈建议您遵守这个惯例。 + +长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性,并且不 +会隐藏信息。子片段要明显短于母片段,并明显靠右。这同样适用于有着很长参数列表 +的函数头。然而,绝对不要打散对用户可见的字符串,例如 printk 信息,因为这样就 +很难对它们 grep。 + + +3) 大括号和空格的放置 +------------------------------ + +C 语言风格中另外一个常见问题是大括号的放置。和缩进大小不同,选择或弃用某种放 +置策略并没有多少技术上的原因,不过首选的方式,就像 Kernighan 和 Ritchie 展示 +给我们的,是把起始大括号放在行尾,而把结束大括号放在行首,所以: + +.. code-block:: c + + if (x is true) { + we do y + } + +这适用于所有的非函数语句块 (if, switch, for, while, do)。比如: + +.. code-block:: c + + switch (action) { + case KOBJ_ADD: + return "add"; + case KOBJ_REMOVE: + return "remove"; + case KOBJ_CHANGE: + return "change"; + default: + return NULL; + } + +不过,有一个例外,那就是函数:函数的起始大括号放置于下一行的开头,所以: + +.. code-block:: c + + int function(int x) + { + body of function + } + +全世界的异端可能会抱怨这个不一致性是... 呃... 不一致的,不过所有思维健全的人 +都知道 (a) K&R 是 **正确的** 并且 (b) K&R 是正确的。此外,不管怎样函数都是特 +殊的 (C 函数是不能嵌套的)。 + +注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是 do 语 +句中的 "while" 或者 if 语句中的 "else",像这样: + +.. code-block:: c + + do { + body of do-loop + } while (condition); + +和 + +.. code-block:: c + + if (x == y) { + .. + } else if (x > y) { + ... + } else { + .... + } + +理由:K&R。 + +也请注意这种大括号的放置方式也能使空 (或者差不多空的) 行的数量最小化,同时不 +失可读性。因此,由于你的屏幕上的新行是不可再生资源 (想想 25 行的终端屏幕),你 +将会有更多的空行来放置注释。 + +当只有一个单独的语句的时候,不用加不必要的大括号。 + +.. code-block:: c + + if (condition) + action(); + +和 + +.. code-block:: c + + if (condition) + do_this(); + else + do_that(); + +这并不适用于只有一个条件分支是单语句的情况;这时所有分支都要使用大括号: + +.. code-block:: c + + if (condition) { + do_this(); + do_that(); + } else { + otherwise(); + } + +3.1) 空格 +******************** + +Linux 内核的空格使用方式 (主要) 取决于它是用于函数还是关键字。(大多数) 关键字 +后要加一个空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,这 +些关键字某些程度上看起来更像函数 (它们在 Linux 里也常常伴随小括号而使用,尽管 +在 C 里这样的小括号不是必需的,就像 ``struct fileinfo info;`` 声明过后的 +``sizeof info``)。 + +所以在这些关键字之后放一个空格:: + + if, switch, case, for, do, while + +但是不要在 sizeof, typeof, alignof 或者 __attribute__ 这些关键字之后放空格。 +例如, + +.. code-block:: c + + s = sizeof(struct file); + +不要在小括号里的表达式两侧加空格。这是一个 **反例** : + +.. code-block:: c + + s = sizeof( struct file ); + +当声明指针类型或者返回指针类型的函数时, ``*`` 的首选使用方式是使之靠近变量名 +或者函数名,而不是靠近类型名。例子: + +.. code-block:: c + + char *linux_banner; + unsigned long long memparse(char *ptr, char **retptr); + char *match_strdup(substring_t *s); + +在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符:: + + = + - < > * / % | & ^ <= >= == != ? : + +但是一元操作符后不要加空格:: + + & * + - ~ ! sizeof typeof alignof __attribute__ defined + +后缀自加和自减一元操作符前不加空格:: + + ++ -- + +前缀自加和自减一元操作符后不加空格:: + + ++ -- + +``.`` 和 ``->`` 结构体成员操作符前后不加空格。 + +不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后 +你就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码,有些编辑器 +就不会移除已经加入的空白,就像你故意留下一个只有空白的行。包含行尾空白的行就 +这样产生了。 + +当 git 发现补丁包含了行尾空白的时候会警告你,并且可以应你的要求去掉行尾空白; +不过如果你是正在打一系列补丁,这样做会导致后面的补丁失败,因为你改变了补丁的 +上下文。 + + +4) 命名 +------------------------------ + +C 是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同, +C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会 +称那个变量为 ``tmp`` ,这样写起来会更容易,而且至少不会令其难于理解。 + +不过,虽然混用大小写的名字是不提倡使用的,但是全局变量还是需要一个具描述性的 +名字。称一个全局函数为 ``foo`` 是一个难以饶恕的错误。 + +全局变量 (只有当你 **真正** 需要它们的时候再用它) 需要有一个具描述性的名字,就 +像全局函数。如果你有一个可以计算活动用户数量的函数,你应该叫它 +``count_active_users()`` 或者类似的名字,你不应该叫它 ``cntuser()`` 。 + +在函数名中包含函数类型 (所谓的匈牙利命名法) 是脑子出了问题——编译器知道那些类 +型而且能够检查那些类型,这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题 +的程序。 + +本地变量名应该简短,而且能够表达相关的含义。如果你有一些随机的整数型的循环计 +数器,它应该被称为 ``i`` 。叫它 ``loop_counter`` 并无益处,如果它没有被误解的 +可能的话。类似的, ``tmp`` 可以用来称呼任意类型的临时变量。 + +如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综 +合症。请看第六章 (函数)。 + + +5) Typedef +----------- + +不要使用类似 ``vps_t`` 之类的东西。 + +对结构体和指针使用 typedef 是一个 **错误** 。当你在代码里看到: + +.. code-block:: c + + vps_t a; + +这代表什么意思呢? + +相反,如果是这样 + +.. code-block:: c + + struct virtual_container *a; + +你就知道 ``a`` 是什么了。 + +很多人认为 typedef ``能提高可读性`` 。实际不是这样的。它们只在下列情况下有用: + + (a) 完全不透明的对象 (这种情况下要主动使用 typedef 来 **隐藏** 这个对象实际上 + 是什么)。 + + 例如: ``pte_t`` 等不透明对象,你只能用合适的访问函数来访问它们。 + + .. note:: + + 不透明性和 "访问函数" 本身是不好的。我们使用 pte_t 等类型的原因在于真 + 的是完全没有任何共用的可访问信息。 + + (b) 清楚的整数类型,如此,这层抽象就可以 **帮助** 消除到底是 ``int`` 还是 + ``long`` 的混淆。 + + u8/u16/u32 是完全没有问题的 typedef,不过它们更符合类别 (d) 而不是这里。 + + .. note:: + + 要这样做,必须事出有因。如果某个变量是 ``unsigned long`` ,那么没有必要 + + typedef unsigned long myflags_t; + + 不过如果有一个明确的原因,比如它在某种情况下可能会是一个 ``unsigned int`` + 而在其他情况下可能为 ``unsigned long`` ,那么就不要犹豫,请务必使用 + typedef。 + + (c) 当你使用 sparse 按字面的创建一个 **新** 类型来做类型检查的时候。 + + (d) 和标准 C99 类型相同的类型,在某些例外的情况下。 + + 虽然让眼睛和脑筋来适应新的标准类型比如 ``uint32_t`` 不需要花很多时间,可 + 是有些人仍然拒绝使用它们。 + + 因此,Linux 特有的等同于标准类型的 ``u8/u16/u32/u64`` 类型和它们的有符号 + 类型是被允许的——尽管在你自己的新代码中,它们不是强制要求要使用的。 + + 当编辑已经使用了某个类型集的已有代码时,你应该遵循那些代码中已经做出的选 + 择。 + + (e) 可以在用户空间安全使用的类型。 + + 在某些用户空间可见的结构体里,我们不能要求 C99 类型而且不能用上面提到的 + ``u32`` 类型。因此,我们在与用户空间共享的所有结构体中使用 __u32 和类似 + 的类型。 + +可能还有其他的情况,不过基本的规则是 **永远不要** 使用 typedef,除非你可以明 +确的应用上述某个规则中的一个。 + +总的来说,如果一个指针或者一个结构体里的元素可以合理的被直接访问到,那么它们 +就不应该是一个 typedef。 + + +6) 函数 +------------------------------ + +函数应该简短而漂亮,并且只完成一件事情。函数应该可以一屏或者两屏显示完 (我们 +都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。 + +一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以,如果你有一个理 +论上很简单的只有一个很长 (但是简单) 的 case 语句的函数,而且你需要在每个 case +里做很多很小的事情,这样的函数尽管很长,但也是可以的。 + +不过,如果你有一个复杂的函数,而且你怀疑一个天分不是很高的高中一年级学生可能 +甚至搞不清楚这个函数的目的,你应该严格遵守前面提到的长度限制。使用辅助函数, +并为之取个具描述性的名字 (如果你觉得它们的性能很重要的话,可以让编译器内联它 +们,这样的效果往往会比你写一个复杂函数的效果要好。) + +函数的另外一个衡量标准是本地变量的数量。此数量不应超过 5-10 个,否则你的函数 +就有问题了。重新考虑一下你的函数,把它分拆成更小的函数。人的大脑一般可以轻松 +的同时跟踪 7 个不同的事物,如果再增多的话,就会糊涂了。即便你聪颖过人,你也可 +能会记不清你 2 个星期前做过的事情。 + +在源文件里,使用空行隔开不同的函数。如果该函数需要被导出,它的 **EXPORT** 宏 +应该紧贴在它的结束大括号之下。比如: + +.. code-block:: c + + int system_is_up(void) + { + return system_state == SYSTEM_RUNNING; + } + EXPORT_SYMBOL(system_is_up); + +在函数原型中,包含函数名和它们的数据类型。虽然 C 语言里没有这样的要求,在 +Linux 里这是提倡的做法,因为这样可以很简单的给读者提供更多的有价值的信息。 + + +7) 集中的函数退出途径 +------------------------------ + +虽然被某些人声称已经过时,但是 goto 语句的等价物还是经常被编译器所使用,具体 +形式是无条件跳转指令。 + +当一个函数从多个位置退出,并且需要做一些类似清理的常见操作时,goto 语句就很方 +便了。如果并不需要清理操作,那么直接 return 即可。 + +选择一个能够说明 goto 行为或它为何存在的标签名。如果 goto 要释放 ``buffer``, +一个不错的名字可以是 ``out_free_buffer:`` 。别去使用像 ``err1:`` 和 ``err2:`` +这样的GW_BASIC 名称,因为一旦你添加或删除了 (函数的) 退出路径,你就必须对它们 +重新编号,这样会难以去检验正确性。 + +使用 goto 的理由是: + +- 无条件语句容易理解和跟踪 +- 嵌套程度减小 +- 可以避免由于修改时忘记更新个别的退出点而导致错误 +- 让编译器省去删除冗余代码的工作 ;) + +.. code-block:: c + + int fun(int a) + { + int result = 0; + char *buffer; + + buffer = kmalloc(SIZE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + if (condition1) { + while (loop1) { + ... + } + result = 1; + goto out_free_buffer; + } + ... + out_free_buffer: + kfree(buffer); + return result; + } + +一个需要注意的常见错误是 ``一个 err 错误`` ,就像这样: + +.. code-block:: c + + err: + kfree(foo->bar); + kfree(foo); + return ret; + +这段代码的错误是,在某些退出路径上 ``foo`` 是 NULL。通常情况下,通过把它分离 +成两个错误标签 ``err_free_bar:`` 和 ``err_free_foo:`` 来修复这个错误: + +.. code-block:: c + + err_free_bar: + kfree(foo->bar); + err_free_foo: + kfree(foo); + return ret; + +理想情况下,你应该模拟错误来测试所有退出路径。 + + +8) 注释 +------------------------------ + +注释是好的,不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的: +更好的做法是让别人一看你的代码就可以明白,解释写的很差的代码是浪费时间。 + +一般的,你想要你的注释告诉别人你的代码做了什么,而不是怎么做的。也请你不要把 +注释放在一个函数体内部:如果函数复杂到你需要独立的注释其中的一部分,你很可能 +需要回到第六章看一看。你可以做一些小注释来注明或警告某些很聪明 (或者槽糕) 的 +做法,但不要加太多。你应该做的,是把注释放在函数的头部,告诉人们它做了什么, +也可以加上它做这些事情的原因。 + +当注释内核 API 函数时,请使用 kernel-doc 格式。请看 +Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。 + +长 (多行) 注释的首选风格是: + +.. code-block:: c + + /* + * This is the preferred style for multi-line + * comments in the Linux kernel source code. + * Please use it consistently. + * + * Description: A column of asterisks on the left side, + * with beginning and ending almost-blank lines. + */ + +对于在 net/ 和 drivers/net/ 的文件,首选的长 (多行) 注释风格有些不同。 + +.. code-block:: c + + /* The preferred comment style for files in net/ and drivers/net + * looks like this. + * + * It is nearly the same as the generally preferred comment style, + * but there is no initial almost-blank line. + */ + +注释数据也是很重要的,不管是基本类型还是衍生类型。为了方便实现这一点,每一行 +应只声明一个数据 (不要使用逗号来一次声明多个数据)。这样你就有空间来为每个数据 +写一段小注释来解释它们的用途了。 + + +9) 你已经把事情弄糟了 +------------------------------ + +这没什么,我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你 +``GNU emacs`` 能自动帮你格式化 C 源代码,而且你也注意到了,确实是这样,不过它 +所使用的默认值和我们想要的相去甚远 (实际上,甚至比随机打的还要差——无数个猴子 +在 GNU emacs 里打字永远不会创造出一个好程序) (译注:Infinite Monkey Theorem) + +所以你要么放弃 GNU emacs,要么改变它让它使用更合理的设定。要采用后一个方案, +你可以把下面这段粘贴到你的 .emacs 文件里。 + +.. code-block:: none + + (defun c-lineup-arglist-tabs-only (ignored) + "Line up argument lists by tabs, not spaces" + (let* ((anchor (c-langelem-pos c-syntactic-element)) + (column (c-langelem-2nd-pos c-syntactic-element)) + (offset (- (1+ column) anchor)) + (steps (floor offset c-basic-offset))) + (* (max steps 1) + c-basic-offset))) + + (dir-locals-set-class-variables + 'linux-kernel + '((c-mode . ( + (c-basic-offset . 8) + (c-label-minimum-indentation . 0) + (c-offsets-alist . ( + (arglist-close . c-lineup-arglist-tabs-only) + (arglist-cont-nonempty . + (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only)) + (arglist-intro . +) + (brace-list-intro . +) + (c . c-lineup-C-comments) + (case-label . 0) + (comment-intro . c-lineup-comment) + (cpp-define-intro . +) + (cpp-macro . -1000) + (cpp-macro-cont . +) + (defun-block-intro . +) + (else-clause . 0) + (func-decl-cont . +) + (inclass . +) + (inher-cont . c-lineup-multi-inher) + (knr-argdecl-intro . 0) + (label . -1000) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-cont . +) + (substatement . +) + )) + (indent-tabs-mode . t) + (show-trailing-whitespace . t) + )))) + + (dir-locals-set-directory-class + (expand-file-name "~/src/linux-trees") + 'linux-kernel) + +这会让 emacs 在 ``~/src/linux-trees`` 下的 C 源文件获得更好的内核代码风格。 + +不过就算你尝试让 emacs 正确的格式化代码失败了,也并不意味着你失去了一切:还可 +以用 ``indent`` 。 + +不过,GNU indent 也有和 GNU emacs 一样有问题的设定,所以你需要给它一些命令选 +项。不过,这还不算太糟糕,因为就算是 GNU indent 的作者也认同 K&R 的权威性 +(GNU 的人并不是坏人,他们只是在这个问题上被严重的误导了),所以你只要给 indent +指定选项 ``-kr -i8`` (代表 ``K&R,8 字符缩进``),或使用 ``scripts/Lindent`` +这样就可以以最时髦的方式缩进源代码。 + +``indent`` 有很多选项,特别是重新格式化注释的时候,你可能需要看一下它的手册。 +不过记住: ``indent`` 不能修正坏的编程习惯。 + + +10) Kconfig 配置文件 +------------------------------ + +对于遍布源码树的所有 Kconfig* 配置文件来说,它们缩进方式有所不同。紧挨着 +``config`` 定义的行,用一个制表符缩进,然而 help 信息的缩进则额外增加 2 个空 +格。举个例子:: + + config AUDIT + bool "Auditing support" + depends on NET + help + Enable auditing infrastructure that can be used with another + kernel subsystem, such as SELinux (which requires this for + logging of avc messages output). Does not do system-call + auditing without CONFIG_AUDITSYSCALL. + +而那些危险的功能 (比如某些文件系统的写支持) 应该在它们的提示字符串里显著的声 +明这一点:: + + config ADFS_FS_RW + bool "ADFS write support (DANGEROUS)" + depends on ADFS_FS + ... + +要查看配置文件的完整文档,请看 Documentation/kbuild/kconfig-language.txt。 + + +11) 数据结构 +------------------------------ + +如果一个数据结构,在创建和销毁它的单线执行环境之外可见,那么它必须要有一个引 +用计数器。内核里没有垃圾收集 (并且内核之外的垃圾收集慢且效率低下),这意味着你 +绝对需要记录你对这种数据结构的使用情况。 + +引用计数意味着你能够避免上锁,并且允许多个用户并行访问这个数据结构——而不需要 +担心这个数据结构仅仅因为暂时不被使用就消失了,那些用户可能不过是沉睡了一阵或 +者做了一些其他事情而已。 + +注意上锁 **不能** 取代引用计数。上锁是为了保持数据结构的一致性,而引用计数是一 +个内存管理技巧。通常二者都需要,不要把两个搞混了。 + +很多数据结构实际上有 2 级引用计数,它们通常有不同 ``类`` 的用户。子类计数器统 +计子类用户的数量,每当子类计数器减至零时,全局计数器减一。 + +这种 ``多级引用计数`` 的例子可以在内存管理 (``struct mm_struct``: mm_users 和 +mm_count),和文件系统 (``struct super_block``: s_count 和 s_active) 中找到。 + +记住:如果另一个执行线索可以找到你的数据结构,但这个数据结构没有引用计数器, +这里几乎肯定是一个 bug。 + + +12) 宏,枚举和RTL +------------------------------ + +用于定义常量的宏的名字及枚举里的标签需要大写。 + +.. code-block:: c + + #define CONSTANT 0x12345 + +在定义几个相关的常量时,最好用枚举。 + +宏的名字请用大写字母,不过形如函数的宏的名字可以用小写字母。 + +一般的,如果能写成内联函数就不要写成像函数的宏。 + +含有多个语句的宏应该被包含在一个 do-while 代码块里: + +.. code-block:: c + + #define macrofun(a, b, c) \ + do { \ + if (a == 5) \ + do_this(b, c); \ + } while (0) + +使用宏的时候应避免的事情: + +1) 影响控制流程的宏: + +.. code-block:: c + + #define FOO(x) \ + do { \ + if (blah(x) < 0) \ + return -EBUGGERED; \ + } while (0) + +**非常** 不好。它看起来像一个函数,不过却能导致 ``调用`` 它的函数退出;不要打 +乱读者大脑里的语法分析器。 + +2) 依赖于一个固定名字的本地变量的宏: + +.. code-block:: c + + #define FOO(val) bar(index, val) + +可能看起来像是个不错的东西,不过它非常容易把读代码的人搞糊涂,而且容易导致看起 +来不相关的改动带来错误。 + +3) 作为左值的带参数的宏: FOO(x) = y;如果有人把 FOO 变成一个内联函数的话,这 + 种用法就会出错了。 + +4) 忘记了优先级:使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数 + 的宏也要注意此类问题。 + +.. code-block:: c + + #define CONSTANT 0x4000 + #define CONSTEXP (CONSTANT | 3) + +5) 在宏里定义类似函数的本地变量时命名冲突: + +.. code-block:: c + + #define FOO(x) \ + ({ \ + typeof(x) ret; \ + ret = calc_ret(x); \ + (ret); \ + }) + +ret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。 + +cpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL,内核里的汇编语 +言经常用到它。 + + +13) 打印内核消息 +------------------------------ + +内核开发者应该是受过良好教育的。请一定注意内核信息的拼写,以给人以好的印象。 +不要用不规范的单词比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保证这些信 +息简单明了,无歧义。 + +内核信息不必以英文句号结束。 + +在小括号里打印数字 (%d) 没有任何价值,应该避免这样做。 + +<linux/device.h> 里有一些驱动模型诊断宏,你应该使用它们,以确保信息对应于正确 +的设备和驱动,并且被标记了正确的消息级别。这些宏有:dev_err(), dev_warn(), +dev_info() 等等。对于那些不和某个特定设备相关连的信息,<linux/printk.h> 定义 +了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。 + +写出好的调试信息可以是一个很大的挑战;一旦你写出后,这些信息在远程除错时能提 +供极大的帮助。然而打印调试信息的处理方式同打印非调试信息不同。其他 pr_XXX() +函数能无条件地打印,pr_debug() 却不;默认情况下它不会被编译,除非定义了 DEBUG +或设定了 CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg(),一个相关约定是在一 +个已经开启了 DEBUG 时,使用 VERBOSE_DEBUG 来添加 dev_vdbg()。 + +许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面;在其他 +情况下,特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时,例如, +如果已经包含一个调试相关的 #ifdef 条件,printk(KERN_DEBUG ...) 就可被使用。 + + +14) 分配内存 +------------------------------ + +内核提供了下面的一般用途的内存分配函数: +kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。 +请参考 API 文档以获取有关它们的详细信息。 + +传递结构体大小的首选形式是这样的: + +.. code-block:: c + + p = kmalloc(sizeof(*p), ...); + +另外一种传递方式中,sizeof 的操作数是结构体的名字,这样会降低可读性,并且可能 +会引入 bug。有可能指针变量类型被改变时,而对应的传递给内存分配函数的 sizeof +的结果不变。 + +强制转换一个 void 指针返回值是多余的。C 语言本身保证了从 void 指针到其他任何 +指针类型的转换是没有问题的。 + +分配一个数组的首选形式是这样的: + +.. code-block:: c + + p = kmalloc_array(n, sizeof(...), ...); + +分配一个零长数组的首选形式是这样的: + +.. code-block:: c + + p = kcalloc(n, sizeof(...), ...); + +两种形式检查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。 + + +15) 内联弊病 +------------------------------ + +有一个常见的误解是 ``内联`` 是 gcc 提供的可以让代码运行更快的一个选项。虽然使 +用内联函数有时候是恰当的 (比如作为一种替代宏的方式,请看第十二章),不过很多情 +况下不是这样。inline 的过度使用会使内核变大,从而使整个系统运行速度变慢。 +因为体积大内核会占用更多的指令高速缓存,而且会导致 pagecache 的可用内存减少。 +想象一下,一次 pagecache 未命中就会导致一次磁盘寻址,将耗时 5 毫秒。5 毫秒的 +时间内 CPU 能执行很多很多指令。 + +一个基本的原则是如果一个函数有 3 行以上,就不要把它变成内联函数。这个原则的一 +个例外是,如果你知道某个参数是一个编译时常量,而且因为这个常量你确定编译器在 +编译时能优化掉你的函数的大部分代码,那仍然可以给它加上 inline 关键字。 +kmalloc() 内联函数就是一个很好的例子。 + +人们经常主张给 static 的而且只用了一次的函数加上 inline,如此不会有任何损失, +因为没有什么好权衡的。虽然从技术上说这是正确的,但是实际上这种情况下即使不加 +inline gcc 也可以自动使其内联。而且其他用户可能会要求移除 inline,由此而来的 +争论会抵消 inline 自身的潜在价值,得不偿失。 + + +16) 函数返回值及命名 +------------------------------ + +函数可以返回多种不同类型的值,最常见的一种是表明函数执行成功或者失败的值。这样 +的一个值可以表示为一个错误代码整数 (-Exxx=失败,0=成功) 或者一个 ``成功`` +布尔值 (0=失败,非0=成功)。 + +混合使用这两种表达方式是难于发现的 bug 的来源。如果 C 语言本身严格区分整形和 +布尔型变量,那么编译器就能够帮我们发现这些错误... 不过 C 语言不区分。为了避免 +产生这种 bug,请遵循下面的惯例:: + + 如果函数的名字是一个动作或者强制性的命令,那么这个函数应该返回错误代 + 码整数。如果是一个判断,那么函数应该返回一个 "成功" 布尔值。 + +比如, ``add work`` 是一个命令,所以 add_work() 在成功时返回 0,在失败时返回 +-EBUSY。类似的,因为 ``PCI device present`` 是一个判断,所以 pci_dev_present() +在成功找到一个匹配的设备时应该返回 1,如果找不到时应该返回 0。 + +所有 EXPORTed 函数都必须遵守这个惯例,所有的公共函数也都应该如此。私有 +(static) 函数不需要如此,但是我们也推荐这样做。 + +返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的, +他们通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数, +他们使用 NULL 或者 ERR_PTR 机制来报告错误。 + + +17) 不要重新发明内核宏 +------------------------------ + +头文件 include/linux/kernel.h 包含了一些宏,你应该使用它们,而不要自己写一些 +它们的变种。比如,如果你需要计算一个数组的长度,使用这个宏 + +.. code-block:: c + + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +类似的,如果你要计算某结构体成员的大小,使用 + +.. code-block:: c + + #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) + +还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以 +自己看看那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应 +在你的代码里自己重新定义。 + + +18) 编辑器模式行和其他需要罗嗦的事情 +-------------------------------------------------- + +有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如,emacs +能够解释被标记成这样的行: + +.. code-block:: c + + -*- mode: c -*- + +或者这样的: + +.. code-block:: c + + /* + Local Variables: + compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" + End: + */ + +Vim 能够解释这样的标记: + +.. code-block:: c + + /* vim:set sw=8 noet */ + +不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置,你的源文件不 +应该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制 +的模式,或者使用其他可以产生正确的缩进的巧妙方法。 + + +19) 内联汇编 +------------------------------ + +在特定架构的代码中,你可能需要内联汇编与 CPU 和平台相关功能连接。需要这么做时 +就不要犹豫。然而,当 C 可以完成工作时,不要平白无故地使用内联汇编。在可能的情 +况下,你可以并且应该用 C 和硬件沟通。 + +请考虑去写捆绑通用位元 (wrap common bits) 的内联汇编的简单辅助函数,别去重复 +地写下只有细微差异内联汇编。记住内联汇编可以使用 C 参数。 + +大型,有一定复杂度的汇编函数应该放在 .S 文件内,用相应的 C 原型定义在 C 头文 +件中。汇编函数的 C 原型应该使用 ``asmlinkage`` 。 + +你可能需要把汇编语句标记为 volatile,用来阻止 GCC 在没发现任何副作用后就把它 +移除了。你不必总是这样做,尽管,这不必要的举动会限制优化。 + +在写一个包含多条指令的单个内联汇编语句时,把每条指令用引号分割而且各占一行, +除了最后一条指令外,在每个指令结尾加上 \n\t,让汇编输出时可以正确地缩进下一条 +指令: + +.. code-block:: c + + asm ("magic %reg1, #42\n\t" + "more_magic %reg2, %reg3" + : /* outputs */ : /* inputs */ : /* clobbers */); + + +20) 条件编译 +------------------------------ + +只要可能,就不要在 .c 文件里面使用预处理条件 (#if, #ifdef);这样做让代码更难 +阅读并且更难去跟踪逻辑。替代方案是,在头文件中用预处理条件提供给那些 .c 文件 +使用,再给 #else 提供一个空桩 (no-op stub) 版本,然后在 .c 文件内无条件地调用 +那些 (定义在头文件内的) 函数。这样做,编译器会避免为桩函数 (stub) 的调用生成 +任何代码,产生的结果是相同的,但逻辑将更加清晰。 + +最好倾向于编译整个函数,而不是函数的一部分或表达式的一部分。与其放一个 ifdef +在表达式内,不如分解出部分或全部表达式,放进一个单独的辅助函数,并应用预处理 +条件到这个辅助函数内。 + +如果你有一个在特定配置中,可能变成未使用的函数或变量,编译器会警告它定义了但 +未使用,把它标记为 __maybe_unused 而不是将它包含在一个预处理条件中。(然而,如 +果一个函数或变量总是未使用,就直接删除它。) + +在代码中,尽可能地使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔 +表达式,并在一般的 C 条件中使用它: + +.. code-block:: c + + if (IS_ENABLED(CONFIG_SOMETHING)) { + ... + } + +编译器会做常量折叠,然后就像使用 #ifdef 那样去包含或排除代码块,所以这不会带 +来任何运行时开销。然而,这种方法依旧允许 C 编译器查看块内的代码,并检查它的正 +确性 (语法,类型,符号引用,等等)。因此,如果条件不满足,代码块内的引用符号就 +不存在时,你还是必须去用 #ifdef。 + +在任何有意义的 #if 或 #ifdef 块的末尾 (超过几行的),在 #endif 同一行的后面写下 +注解,注释这个条件表达式。例如: + +.. code-block:: c + + #ifdef CONFIG_SOMETHING + ... + #endif /* CONFIG_SOMETHING */ + + +附录 I) 参考 +------------------- + +The C Programming Language, 第二版 +作者:Brian W. Kernighan 和 Denni M. Ritchie. +Prentice Hall, Inc., 1988. +ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮). + +The Practice of Programming +作者:Brian W. Kernighan 和 Rob Pike. +Addison-Wesley, Inc., 1999. +ISBN 0-201-61586-X. + +GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent, +都可以从 http://www.gnu.org/manual/ 找到 + +WG14 是 C 语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/ + +Kernel process/coding-style.rst,作者 greg@kroah.com 发表于 OLS 2002: +http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ diff --git a/Documentation/translations/zh_CN/process/development-process.rst b/Documentation/translations/zh_CN/process/development-process.rst new file mode 100644 index 000000000000..30cffe66c075 --- /dev/null +++ b/Documentation/translations/zh_CN/process/development-process.rst @@ -0,0 +1,26 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/development-process.rst <development_process_main>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_development_process_main: + +内核开发过程指南 +================ + +内容: + +.. toctree:: + :numbered: + :maxdepth: 2 + + 1.Intro + 2.Process + 3.Early-stage + 4.Coding + 5.Posting + 6.Followthrough + 7.AdvancedTopics + 8.Conclusion + +本文档的目的是帮助开发人员(及其经理)以最小的挫折感与开发社区合作。它试图记录这个社区如何以一种不熟悉Linux内核开发(或者实际上是自由软件开发)的人可以访问的方式工作。虽然这里有一些技术资料,但这是一个面向过程的讨论,不需要深入了解内核编程就可以理解。 diff --git a/Documentation/translations/zh_CN/process/email-clients.rst b/Documentation/translations/zh_CN/process/email-clients.rst new file mode 100644 index 000000000000..102023651118 --- /dev/null +++ b/Documentation/translations/zh_CN/process/email-clients.rst @@ -0,0 +1,248 @@ +.. _cn_email_clients: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/email-clients.rst <email_clients>` + +译者:: + + 中文版维护者: 贾威威 Harry Wei <harryxiyou@gmail.com> + 中文版翻译者: 贾威威 Harry Wei <harryxiyou@gmail.com> + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + 中文版校译者: Yinglin Luan <synmyth@gmail.com> + Xiaochen Wang <wangxiaochen0@gmail.com> + yaxinsn <yaxinsn@163.com> + +Linux邮件客户端配置信息 +======================= + +Git +--- + +现在大多数开发人员使用 ``git send-email`` 而不是常规的电子邮件客户端。这方面 +的手册非常好。在接收端,维护人员使用 ``git am`` 加载补丁。 + +如果你是 ``git`` 新手,那么把你的第一个补丁发送给你自己。将其保存为包含所有 +标题的原始文本。运行 ``git am raw_email.txt`` ,然后使用 ``git log`` 查看更 +改日志。如果工作正常,再将补丁发送到相应的邮件列表。 + + +普通配置 +-------- +Linux内核补丁是通过邮件被提交的,最好把补丁作为邮件体的内嵌文本。有些维护者 +接收附件,但是附件的内容格式应该是"text/plain"。然而,附件一般是不赞成的, +因为这会使补丁的引用部分在评论过程中变的很困难。 + +用来发送Linux内核补丁的邮件客户端在发送补丁时应该处于文本的原始状态。例如, +他们不能改变或者删除制表符或者空格,甚至是在每一行的开头或者结尾。 + +不要通过"format=flowed"模式发送补丁。这样会引起不可预期以及有害的断行。 + +不要让你的邮件客户端进行自动换行。这样也会破坏你的补丁。 + +邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码方式, +如果你使用UTF-8编码方式发送邮件,那么你将会避免一些可能发生的字符集问题。 + +邮件客户端应该形成并且保持 References: 或者 In-Reply-To: 标题,那么 +邮件话题就不会中断。 + +复制粘帖(或者剪贴粘帖)通常不能用于补丁,因为制表符会转换为空格。使用xclipboard, xclip +或者xcutsel也许可以,但是最好测试一下或者避免使用复制粘帖。 + +不要在使用PGP/GPG署名的邮件中包含补丁。这样会使得很多脚本不能读取和适用于你的补丁。 +(这个问题应该是可以修复的) + +在给内核邮件列表发送补丁之前,给自己发送一个补丁是个不错的主意,保存接收到的 +邮件,将补丁用'patch'命令打上,如果成功了,再给内核邮件列表发送。 + + +一些邮件客户端提示 +------------------ +这里给出一些详细的MUA配置提示,可以用于给Linux内核发送补丁。这些并不意味是 +所有的软件包配置总结。 + +说明: +TUI = 以文本为基础的用户接口 +GUI = 图形界面用户接口 + +Alpine (TUI) +~~~~~~~~~~~~ + +配置选项: +在"Sending Preferences"部分: + +- "Do Not Send Flowed Text"必须开启 +- "Strip Whitespace Before Sending"必须关闭 + +当写邮件时,光标应该放在补丁会出现的地方,然后按下CTRL-R组合键,使指定的 +补丁文件嵌入到邮件中。 + +Evolution (GUI) +~~~~~~~~~~~~~~~ + +一些开发者成功的使用它发送补丁 + +当选择邮件选项:Preformat + 从Format->Heading->Preformatted (Ctrl-7)或者工具栏 + +然后使用: + Insert->Text File... (Alt-n x)插入补丁文件。 + +你还可以"diff -Nru old.c new.c | xclip",选择Preformat,然后使用中间键进行粘帖。 + +Kmail (GUI) +~~~~~~~~~~~ + +一些开发者成功的使用它发送补丁。 + +默认设置不为HTML格式是合适的;不要启用它。 + +当书写一封邮件的时候,在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输入的任何文本 +都不会被自动换行,因此你必须在发送补丁之前手动换行。最简单的方法就是启用自动换行来书写邮件, +然后把它保存为草稿。一旦你在草稿中再次打开它,它已经全部自动换行了,那么你的邮件虽然没有 +选择自动换行,但是还不会失去已有的自动换行。 + +在邮件的底部,插入补丁之前,放上常用的补丁定界符:三个连字号(---)。 + +然后在"Message"菜单条目,选择插入文件,接着选取你的补丁文件。还有一个额外的选项,你可以 +通过它配置你的邮件建立工具栏菜单,还可以带上"insert file"图标。 + +你可以安全地通过GPG标记附件,但是内嵌补丁最好不要使用GPG标记它们。作为内嵌文本的签发补丁, +当从GPG中提取7位编码时会使他们变的更加复杂。 + +如果你非要以附件的形式发送补丁,那么就右键点击附件,然后选中属性,突出"Suggest automatic +display",这样内嵌附件更容易让读者看到。 + +当你要保存将要发送的内嵌文本补丁,你可以从消息列表窗格选择包含补丁的邮件,然后右击选择 +"save as"。你可以使用一个没有更改的包含补丁的邮件,如果它是以正确的形式组成。当你正真在它 +自己的窗口之下察看,那时没有选项可以保存邮件--已经有一个这样的bug被汇报到了kmail的bugzilla +并且希望这将会被处理。邮件是以只针对某个用户可读写的权限被保存的,所以如果你想把邮件复制到其他地方, +你不得不把他们的权限改为组或者整体可读。 + +Lotus Notes (GUI) +~~~~~~~~~~~~~~~~~ + +不要使用它。 + +Mutt (TUI) +~~~~~~~~~~ + +很多Linux开发人员使用mutt客户端,所以证明它肯定工作的非常漂亮。 + +Mutt不自带编辑器,所以不管你使用什么编辑器都不应该带有自动断行。大多数编辑器都带有 +一个"insert file"选项,它可以通过不改变文件内容的方式插入文件。 + +'vim'作为mutt的编辑器: + set editor="vi" + + 如果使用xclip,敲入以下命令 + :set paste + 按中键之前或者shift-insert或者使用 + :r filename + +如果想要把补丁作为内嵌文本。 +(a)ttach工作的很好,不带有"set paste"。 + +你可以通过 ``git format-patch`` 生成补丁,然后用 Mutt发送它们:: + + $ mutt -H 0001-some-bug-fix.patch + +配置选项: +它应该以默认设置的形式工作。 +然而,把"send_charset"设置为"us-ascii::utf-8"也是一个不错的主意。 + +Mutt 是高度可配置的。 这里是个使用mutt通过 Gmail 发送的补丁的最小配置:: + + # .muttrc + # ================ IMAP ==================== + set imap_user = 'yourusername@gmail.com' + set imap_pass = 'yourpassword' + set spoolfile = imaps://imap.gmail.com/INBOX + set folder = imaps://imap.gmail.com/ + set record="imaps://imap.gmail.com/[Gmail]/Sent Mail" + set postponed="imaps://imap.gmail.com/[Gmail]/Drafts" + set mbox="imaps://imap.gmail.com/[Gmail]/All Mail" + + # ================ SMTP ==================== + set smtp_url = "smtp://username@smtp.gmail.com:587/" + set smtp_pass = $imap_pass + set ssl_force_tls = yes # Require encrypted connection + + # ================ Composition ==================== + set editor = `echo \$EDITOR` + set edit_headers = yes # See the headers when editing + set charset = UTF-8 # value of $LANG; also fallback for send_charset + # Sender, email address, and sign-off line must match + unset use_domain # because joe@localhost is just embarrassing + set realname = "YOUR NAME" + set from = "username@gmail.com" + set use_from = yes + +Mutt文档含有更多信息: + + http://dev.mutt.org/trac/wiki/UseCases/Gmail + + http://dev.mutt.org/doc/manual.html + +Pine (TUI) +~~~~~~~~~~ + +Pine过去有一些空格删减问题,但是这些现在应该都被修复了。 + +如果可以,请使用alpine(pine的继承者) + +配置选项: +- 最近的版本需要消除流程文本 +- "no-strip-whitespace-before-send"选项也是需要的。 + + +Sylpheed (GUI) +~~~~~~~~~~~~~~ + +- 内嵌文本可以很好的工作(或者使用附件)。 +- 允许使用外部的编辑器。 +- 对于目录较多时非常慢。 +- 如果通过non-SSL连接,无法使用TLS SMTP授权。 +- 在组成窗口中有一个很有用的ruler bar。 +- 给地址本中添加地址就不会正确的了解显示名。 + +Thunderbird (GUI) +~~~~~~~~~~~~~~~~~ + +默认情况下,thunderbird很容易损坏文本,但是还有一些方法可以强制它变得更好。 + +- 在用户帐号设置里,组成和寻址,不要选择"Compose messages in HTML format"。 + +- 编辑你的Thunderbird配置设置来使它不要拆行使用:user_pref("mailnews.wraplength", 0); + +- 编辑你的Thunderbird配置设置,使它不要使用"format=flowed"格式:user_pref("mailnews. + send_plaintext_flowed", false); + +- 你需要使Thunderbird变为预先格式方式: + 如果默认情况下你书写的是HTML格式,那不是很难。仅仅从标题栏的下拉框中选择"Preformat"格式。 + 如果默认情况下你书写的是文本格式,你不得把它改为HTML格式(仅仅作为一次性的)来书写新的消息, + 然后强制使它回到文本格式,否则它就会拆行。要实现它,在写信的图标上使用shift键来使它变为HTML + 格式,然后标题栏的下拉框中选择"Preformat"格式。 + +- 允许使用外部的编辑器: + 针对Thunderbird打补丁最简单的方法就是使用一个"external editor"扩展,然后使用你最喜欢的 + $EDITOR来读取或者合并补丁到文本中。要实现它,可以下载并且安装这个扩展,然后添加一个使用它的 + 按键View->Toolbars->Customize...最后当你书写信息的时候仅仅点击它就可以了。 + +TkRat (GUI) +~~~~~~~~~~~ + +可以使用它。使用"Insert file..."或者外部的编辑器。 + +Gmail (Web GUI) +~~~~~~~~~~~~~~~ + +不要使用它发送补丁。 + +Gmail网页客户端自动地把制表符转换为空格。 + +虽然制表符转换为空格问题可以被外部编辑器解决,同时它还会使用回车换行把每行拆分为78个字符。 + +另一个问题是Gmail还会把任何不是ASCII的字符的信息改为base64编码。它把东西变的像欧洲人的名字。 + + ### diff --git a/Documentation/translations/zh_CN/process/howto.rst b/Documentation/translations/zh_CN/process/howto.rst new file mode 100644 index 000000000000..5b671178b17b --- /dev/null +++ b/Documentation/translations/zh_CN/process/howto.rst @@ -0,0 +1,492 @@ +.. _cn_process_howto: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/howto.rst <process_howto>` + +译者:: + + 英文版维护者: Greg Kroah-Hartman <greg@kroah.com> + 中文版维护者: 李阳 Li Yang <leoyang.li@nxp.com> + 中文版翻译者: 李阳 Li Yang <leoyang.li@nxp.com> + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + 中文版校译者: + 钟宇 TripleX Chung <xxx.phy@gmail.com> + 陈琦 Maggie Chen <chenqi@beyondsoft.com> + 王聪 Wang Cong <xiyou.wangcong@gmail.com> + +如何参与Linux内核开发 +===================== + +这是一篇将如何参与Linux内核开发的相关问题一网打尽的终极秘笈。它将指导你 +成为一名Linux内核开发者,并且学会如何同Linux内核开发社区合作。它尽可能不 +包括任何关于内核编程的技术细节,但会给你指引一条获得这些知识的正确途径。 + +如果这篇文章中的任何内容不再适用,请给文末列出的文件维护者发送补丁。 + + +入门 +---- + +你想了解如何成为一名Linux内核开发者?或者老板吩咐你“给这个设备写个Linux +驱动程序”?这篇文章的目的就是教会你达成这些目标的全部诀窍,它将描述你需 +要经过的流程以及给出如何同内核社区合作的一些提示。它还将试图解释内核社区 +为何这样运作。 + +Linux内核大部分是由C语言写成的,一些体系结构相关的代码用到了汇编语言。要 +参与内核开发,你必须精通C语言。除非你想为某个架构开发底层代码,否则你并 +不需要了解(任何体系结构的)汇编语言。下面列举的书籍虽然不能替代扎实的C +语言教育和多年的开发经验,但如果需要的话,做为参考还是不错的: + + - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall] + 《C程序设计语言(第2版·新版)》(徐宝文 李志 译)[机械工业出版社] + - "Practical C Programming" by Steve Oualline [O'Reilly] + 《实用C语言编程(第三版)》(郭大海 译)[中国电力出版社] + - "C: A Reference Manual" by Harbison and Steele [Prentice Hall] + 《C语言参考手册(原书第5版)》(邱仲潘 等译)[机械工业出版社] + +Linux内核使用GNU C和GNU工具链开发。虽然它遵循ISO C89标准,但也用到了一些 +标准中没有定义的扩展。内核是自给自足的C环境,不依赖于标准C库的支持,所以 +并不支持C标准中的部分定义。比如long long类型的大数除法和浮点运算就不允许 +使用。有时候确实很难弄清楚内核对工具链的要求和它所使用的扩展,不幸的是目 +前还没有明确的参考资料可以解释它们。请查阅gcc信息页(使用“info gcc”命令 +显示)获得一些这方面信息。 + +请记住你是在学习怎么和已经存在的开发社区打交道。它由一群形形色色的人组成, +他们对代码、风格和过程有着很高的标准。这些标准是在长期实践中总结出来的, +适应于地理上分散的大型开发团队。它们已经被很好得整理成档,建议你在开发 +之前尽可能多的学习这些标准,而不要期望别人来适应你或者你公司的行为方式。 + + +法律问题 +-------- + +Linux内核源代码都是在GPL(通用公共许可证)的保护下发布的。要了解这种许可 +的细节请查看源代码主目录下的COPYING文件。Linux内核许可准则和如何使用 +`SPDX <https://spdx.org/>` 标志符说明在这个文件中 +:ref:`Documentation/translations/zh_CN/process/license-rules.rst <cn_kernel_licensing>` +如果你对它还有更深入问题请联系律师,而不要在Linux内核邮件组上提问。因为 +邮件组里的人并不是律师,不要期望他们的话有法律效力。 + +对于GPL的常见问题和解答,请访问以下链接: + http://www.gnu.org/licenses/gpl-faq.html + + +文档 +---- + +Linux内核代码中包含有大量的文档。这些文档对于学习如何与内核社区互动有着 +不可估量的价值。当一个新的功能被加入内核,最好把解释如何使用这个功能的文 +档也放进内核。当内核的改动导致面向用户空间的接口发生变化时,最好将相关信 +息或手册页(manpages)的补丁发到mtk.manpages@gmail.com,以向手册页(manpages) +的维护者解释这些变化。 + +以下是内核代码中需要阅读的文档: + :ref:`Documentation/admin-guide/README.rst <readme>` + 文件简要介绍了Linux内核的背景,并且描述了如何配置和编译内核。内核的 + 新用户应该从这里开始。 + + + :ref:`Documentation/process/changes.rst <changes>` + 文件给出了用来编译和使用内核所需要的最小软件包列表。 + + :ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>` + 描述Linux内核的代码风格和理由。所有新代码需要遵守这篇文档中定义的规 + 范。大多数维护者只会接收符合规定的补丁,很多人也只会帮忙检查符合风格 + 的代码。 + + :ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` + :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>` + + 这两份文档明确描述如何创建和发送补丁,其中包括(但不仅限于): + - 邮件内容 + - 邮件格式 + - 选择收件人 + + 遵守这些规定并不能保证提交成功(因为所有补丁需要通过严格的内容和风格 + 审查),但是忽视他们几乎就意味着失败。 + + 其他关于如何正确地生成补丁的优秀文档包括: + "The Perfect Patch" + + http://www.ozlabs.org/~akpm/stuff/tpp.txt + + "Linux kernel patch submission format" + + http://linux.yyz.us/patch-format.html + + :ref:`Documentation/translations/zh_CN/process/stable-api-nonsense.rst <cn_stable_api_nonsense>` + 论证内核为什么特意不包括稳定的内核内部API,也就是说不包括像这样的特 + 性: + + - 子系统中间层(为了兼容性?) + - 在不同操作系统间易于移植的驱动程序 + - 减缓(甚至阻止)内核代码的快速变化 + + 这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系 + 统转移到Linux的人来说也很重要。 + + :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>` + 如果你认为自己发现了Linux内核的安全性问题,请根据这篇文档中的步骤来 + 提醒其他内核开发者并帮助解决这个问题。 + + :ref:`Documentation/translations/zh_CN/process/management-style.rst <cn_managementstyle>` + + 描述内核维护者的工作方法及其共有特点。这对于刚刚接触内核开发(或者对 + 它感到好奇)的人来说很重要,因为它解释了很多对于内核维护者独特行为的 + 普遍误解与迷惑。 + + :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>` + 解释了稳定版内核发布的规则,以及如何将改动放入这些版本的步骤。 + + :ref:`Documentation/process/kernel-docs.rst <kernel_docs>` + 有助于内核开发的外部文档列表。如果你在内核自带的文档中没有找到你想找 + 的内容,可以查看这些文档。 + + :ref:`Documentation/process/applying-patches.rst <applying_patches>` + 关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍 + +内核还拥有大量从代码自动生成的文档。它包含内核内部API的全面介绍以及如何 +妥善处理加锁的规则。生成的文档会放在 Documentation/DocBook/目录下。在内 +核源码的主目录中使用以下不同命令将会分别生成PDF、Postscript、HTML和手册 +页等不同格式的文档:: + + make pdfdocs + make htmldocs + + +如何成为内核开发者 +------------------ +如果你对Linux内核开发一无所知,你应该访问“Linux内核新手”计划: + + http://kernelnewbies.org + +它拥有一个可以问各种最基本的内核开发问题的邮件列表(在提问之前一定要记得 +查找已往的邮件,确认是否有人已经回答过相同的问题)。它还拥有一个可以获得 +实时反馈的IRC聊天频道,以及大量对于学习Linux内核开发相当有帮助的文档。 + +网站简要介绍了源代码组织结构、子系统划分以及目前正在进行的项目(包括内核 +中的和单独维护的)。它还提供了一些基本的帮助信息,比如如何编译内核和打补 +丁。 + +如果你想加入内核开发社区并协助完成一些任务,却找不到从哪里开始,可以访问 +“Linux内核房管员”计划: + + http://kernelnewbies.org/KernelJanitors + +这是极佳的起点。它提供一个相对简单的任务列表,列出内核代码中需要被重新 +整理或者改正的地方。通过和负责这个计划的开发者们一同工作,你会学到将补丁 +集成进内核的基本原理。如果还没有决定下一步要做什么的话,你还可能会得到方 +向性的指点。 + +在真正动手修改内核代码之前,理解要修改的代码如何运作是必需的。要达到这个 +目的,没什么办法比直接读代码更有效了(大多数花招都会有相应的注释),而且 +一些特制的工具还可以提供帮助。例如,“Linux代码交叉引用”项目就是一个值得 +特别推荐的帮助工具,它将源代码显示在有编目和索引的网页上。其中一个更新及 +时的内核源码库,可以通过以下地址访问: + + https://elixir.bootlin.com/ + + +开发流程 +-------- + +目前Linux内核开发流程包括几个“主内核分支”和很多子系统相关的内核分支。这 +些分支包括: + + - Linus 的内核源码树 + - 多个主要版本的稳定版内核树 + - 子系统相关的内核树 + - linux-next 集成测试树 + + +主线树 +------ +主线树是由Linus Torvalds 维护的。你可以在https://kernel.org 网站或者代码 +库中下找到它。它的开发遵循以下步骤: + + - 每当一个新版本的内核被发布,为期两周的集成窗口将被打开。在这段时间里 + 维护者可以向Linus提交大段的修改,通常这些修改已经被放到-mm内核中几个 + 星期了。提交大量修改的首选方式是使用git工具(内核的代码版本管理工具 + ,更多的信息可以在 http://git-scm.com/ 获取),不过使用普通补丁也是 + 可以的。 + - 两个星期以后-rc1版本内核发布。之后只有不包含可能影响整个内核稳定性的 + 新功能的补丁才可能被接受。请注意一个全新的驱动程序(或者文件系统)有 + 可能在-rc1后被接受是因为这样的修改完全独立,不会影响其他的代码,所以 + 没有造成内核退步的风险。在-rc1以后也可以用git向Linus提交补丁,不过所 + 有的补丁需要同时被发送到相应的公众邮件列表以征询意见。 + - 当Linus认为当前的git源码树已经达到一个合理健全的状态足以发布供人测试 + 时,一个新的-rc版本就会被发布。计划是每周都发布新的-rc版本。 + - 这个过程一直持续下去直到内核被认为达到足够稳定的状态,持续时间大概是 + 6个星期。 + +关于内核发布,值得一提的是Andrew Morton在linux-kernel邮件列表中如是说: + “没有人知道新内核何时会被发布,因为发布是根据已知bug的情况来决定 + 的,而不是根据一个事先制定好的时间表。” + +子系统特定树 +------------ + +各种内核子系统的维护者——以及许多内核子系统开发人员——在源代码库中公开了他们 +当前的开发状态。这样,其他人就可以看到内核的不同区域发生了什么。在开发速度 +很快的领域,可能会要求开发人员将提交的内容建立在这样的子系统内核树上,这样 +就避免了提交与其他已经进行的工作之间的冲突。 + +这些存储库中的大多数都是Git树,但是也有其他的scm在使用,或者补丁队列被发布 +为Quilt系列。这些子系统存储库的地址列在MAINTAINERS文件中。其中许多可以在 +https://git.kernel.org/上浏览。 + +在将一个建议的补丁提交到这样的子系统树之前,需要对它进行审查,审查主要发生 +在邮件列表上(请参见下面相应的部分)。对于几个内核子系统,这个审查过程是通 +过工具补丁跟踪的。Patchwork提供了一个Web界面,显示补丁发布、对补丁的任何评 +论或修订,维护人员可以将补丁标记为正在审查、接受或拒绝。大多数补丁网站都列 +在 https://patchwork.kernel.org/ + +Linux-next 集成测试树 +--------------------- + +在将子系统树的更新合并到主线树之前,需要对它们进行集成测试。为此,存在一个 +特殊的测试存储库,其中几乎每天都会提取所有子系统树: + + https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git + +通过这种方式,Linux-next 对下一个合并阶段将进入主线内核的内容给出了一个概要 +展望。非常欢冒险的测试者运行测试Linux-next。 + +多个主要版本的稳定版内核树 +----------------------------------- +由3个数字组成的内核版本号说明此内核是-stable版本。它们包含内核的相对较小且 +至关重要的修补,这些修补针对安全性问题或者严重的内核退步。 + +这种版本的内核适用于那些期望获得最新的稳定版内核并且不想参与测试开发版或 +者实验版的用户。 + +稳定版内核树版本由“稳定版”小组(邮件地址<stable@vger.kernel.org>)维护,一般 +隔周发布新版本。 + +内核源码中的 :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>` +文件具体描述了可被稳定版内核接受的修改类型以及发布的流程。 + + +报告bug +------- + +bugzilla.kernel.org是Linux内核开发者们用来跟踪内核Bug的网站。我们鼓励用 +户在这个工具中报告找到的所有bug。如何使用内核bugzilla的细节请访问: + + http://test.kernel.org/bugzilla/faq.html + +内核源码主目录中的:ref:`admin-guide/reporting-bugs.rst <reportingbugs>` +文件里有一个很好的模板。它指导用户如何报告可能的内核bug以及需要提供哪些信息 +来帮助内核开发者们找到问题的根源。 + + +利用bug报告 +----------- + +练习内核开发技能的最好办法就是修改其他人报告的bug。你不光可以帮助内核变 +得更加稳定,还可以学会如何解决实际问题从而提高自己的技能,并且让其他开发 +者感受到你的存在。修改bug是赢得其他开发者赞誉的最好办法,因为并不是很多 +人都喜欢浪费时间去修改别人报告的bug。 + +要尝试修改已知的bug,请访问 http://bugzilla.kernel.org 网址。 + + +邮件列表 +-------- + +正如上面的文档所描述,大多数的骨干内核开发者都加入了Linux Kernel邮件列 +表。如何订阅和退订列表的细节可以在这里找到: + + http://vger.kernel.org/vger-lists.html#linux-kernel + +网上很多地方都有这个邮件列表的存档(archive)。可以使用搜索引擎来找到这些 +存档。比如: + + http://dir.gmane.org/gmane.linux.kernel + +在发信之前,我们强烈建议你先在存档中搜索你想要讨论的问题。很多已经被详细 +讨论过的问题只在邮件列表的存档中可以找到。 + +大多数内核子系统也有自己独立的邮件列表来协调各自的开发工作。从 +MAINTAINERS文件中可以找到不同话题对应的邮件列表。 + +很多邮件列表架设在kernel.org服务器上。这些列表的信息可以在这里找到: + + http://vger.kernel.org/vger-lists.html + +在使用这些邮件列表时,请记住保持良好的行为习惯。下面的链接提供了与这些列 +表(或任何其它邮件列表)交流的一些简单规则,虽然内容有点滥竽充数。 + + http://www.albion.com/netiquette/ + +当有很多人回复你的邮件时,邮件的抄送列表会变得很长。请不要将任何人从抄送 +列表中删除,除非你有足够的理由这么做。也不要只回复到邮件列表。请习惯于同 +一封邮件接收两次(一封来自发送者一封来自邮件列表),而不要试图通过添加一 +些奇特的邮件头来解决这个问题,人们不会喜欢的。 + +记住保留你所回复内容的上下文和源头。在你回复邮件的顶部保留“某某某说到……” +这几行。将你的评论加在被引用的段落之间而不要放在邮件的顶部。 + +如果你在邮件中附带补丁,请确认它们是可以直接阅读的纯文本(如 +:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` +文档中所述)。内核开发者们不希望遇到附件或者被压缩了的补丁。只有这样才能 +保证他们可以直接评论你的每行代码。请确保你使用的邮件发送程序不会修改空格 +和制表符。一个防范性的测试方法是先将邮件发送给自己,然后自己尝试是否可以 +顺利地打上收到的补丁。如果测试不成功,请调整或者更换你的邮件发送程序直到 +它正确工作为止。 + +总而言之,请尊重其他的邮件列表订阅者。 + + +同内核社区合作 +---------------- + +内核社区的目标就是提供尽善尽美的内核。所以当你提交补丁期望被接受进内核的 +时候,它的技术价值以及其他方面都将被评审。那么你可能会得到什么呢? + + - 批评 + - 评论 + - 要求修改 + - 要求证明修改的必要性 + - 沉默 + +要记住,这些是把补丁放进内核的正常情况。你必须学会听取对补丁的批评和评论, +从技术层面评估它们,然后要么重写你的补丁要么简明扼要地论证修改是不必要 +的。如果你发的邮件没有得到任何回应,请过几天后再试一次,因为有时信件会湮 +没在茫茫信海中。 + +你不应该做的事情: + + - 期望自己的补丁不受任何质疑就直接被接受 + - 翻脸 + - 忽略别人的评论 + - 没有按照别人的要求做任何修改就重新提交 + +在一个努力追寻最好技术方案的社区里,对于一个补丁有多少好处总会有不同的见 +解。你必须要抱着合作的态度,愿意改变自己的观点来适应内核的风格。或者至少 +愿意去证明你的想法是有价值的。记住,犯错误是允许的,只要你愿意朝着正确的 +方案去努力。 + +如果你的第一个补丁换来的是一堆修改建议,这是很正常的。这并不代表你的补丁 +不会被接受,也不意味着有人和你作对。你只需要改正所有提出的问题然后重新发 +送你的补丁。 + +内核社区和公司文化的差异 +------------------------ + +内核社区的工作模式同大多数传统公司开发队伍的工作模式并不相同。下面这些例 +子,可以帮助你避免某些可能发生问题: +用这些话介绍你的修改提案会有好处: + + - 它同时解决了多个问题 + - 它删除了2000行代码 + - 这是补丁,它已经解释了我想要说明的 + - 我在5种不同的体系结构上测试过它…… + - 这是一系列小补丁用来…… + - 这个修改提高了普通机器的性能…… + +应该避免如下的说法: + + - 我们在AIX/ptx/Solaris就是这么做的,所以这么做肯定是好的…… + - 我做这行已经20年了,所以…… + - 为了我们公司赚钱考虑必须这么做 + - 这是我们的企业产品线所需要的 + - 这里是描述我观点的1000页设计文档 + - 这是一个5000行的补丁用来…… + - 我重写了现在乱七八糟的代码,这就是…… + - 我被规定了最后期限,所以这个补丁需要立刻被接受 + +另外一个内核社区与大部分传统公司的软件开发队伍不同的地方是无法面对面地交 +流。使用电子邮件和IRC聊天工具做为主要沟通工具的一个好处是性别和种族歧视 +将会更少。Linux内核的工作环境更能接受妇女和少数族群,因为每个人在别人眼 +里只是一个邮件地址。国际化也帮助了公平的实现,因为你无法通过姓名来判断人 +的性别。男人有可能叫李丽,女人也有可能叫王刚。大多数在Linux内核上工作过 +并表达过看法的女性对在linux上工作的经历都给出了正面的评价。 + +对于一些不习惯使用英语的人来说,语言可能是一个引起问题的障碍。在邮件列表 +中要正确地表达想法必需良好地掌握语言,所以建议你在发送邮件之前最好检查一 +下英文写得是否正确。 + + +拆分修改 +-------- + +Linux内核社区并不喜欢一下接收大段的代码。修改需要被恰当地介绍、讨论并且 +拆分成独立的小段。这几乎完全和公司中的习惯背道而驰。你的想法应该在开发最 +开始的阶段就让大家知道,这样你就可以及时获得对你正在进行的开发的反馈。这 +样也会让社区觉得你是在和他们协作,而不是仅仅把他们当作倾销新功能的对象。 +无论如何,你不要一次性地向邮件列表发送50封信,你的补丁序列应该永远用不到 +这么多。 + +将补丁拆开的原因如下: + +1) 小的补丁更有可能被接受,因为它们不需要太多的时间和精力去验证其正确性。 + 一个5行的补丁,可能在维护者看了一眼以后就会被接受。而500行的补丁则 + 需要数个小时来审查其正确性(所需时间随补丁大小增加大约呈指数级增长)。 + + 当出了问题的时候,小的补丁也会让调试变得非常容易。一个一个补丁地回溯 + 将会比仔细剖析一个被打上的大补丁(这个补丁破坏了其他东西)容易得多。 + +2)不光发送小的补丁很重要,在提交之前重新编排、化简(或者仅仅重新排列) + 补丁也是很重要的。 + +这里有内核开发者Al Viro打的一个比方: + “想象一个老师正在给学生批改数学作业。老师并不希望看到学生为了得 + 到正确解法所进行的尝试和产生的错误。他希望看到的是最干净最优雅的 + 解答。好学生了解这点,绝不会把最终解决之前的中间方案提交上去。” + + 内核开发也是这样。维护者和评审者不希望看到一个人在解决问题时的思 + 考过程。他们只希望看到简单和优雅的解决方案。 + +直接给出一流的解决方案,和社区一起协作讨论尚未完成的工作,这两者之间似乎 +很难找到一个平衡点。所以最好尽早开始收集有利于你进行改进的反馈;同时也要 +保证修改分成很多小块,这样在整个项目都准备好被包含进内核之前,其中的一部 +分可能会先被接收。 + +必须了解这样做是不可接受的:试图将未完成的工作提交进内核,然后再找时间修 +复。 + + +证明修改的必要性 +---------------- +除了将补丁拆成小块,很重要的一点是让Linux社区了解他们为什么需要这样修改。 +你必须证明新功能是有人需要的并且是有用的。 + + +记录修改 +-------- + +当你发送补丁的时候,需要特别留意邮件正文的内容。因为这里的信息将会做为补 +丁的修改记录(ChangeLog),会被一直保留以备大家查阅。它需要完全地描述补丁, +包括: + + - 为什么需要这个修改 + - 补丁的总体设计 + - 实现细节 + - 测试结果 + +想了解它具体应该看起来像什么,请查阅以下文档中的“ChangeLog”章节: + “The Perfect Patch” + http://www.ozlabs.org/~akpm/stuff/tpp.txt + + +这些事情有时候做起来很难。要在任何方面都做到完美可能需要好几年时间。这是 +一个持续提高的过程,它需要大量的耐心和决心。只要不放弃,你一定可以做到。 +很多人已经做到了,而他们都曾经和现在的你站在同样的起点上。 + + +感谢 +---- +感谢Paolo Ciarrocchi允许“开发流程”部分基于他所写的文章 +(http://www.kerneltravel.net/newbie/2.6-development_process),感谢Randy +Dunlap和Gerrit Huizenga完善了应该说和不该说的列表。感谢Pat Mochel, Hanna +Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer, +Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian +Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael +Kerrisk和Alex Shepard的评审、建议和贡献。没有他们的帮助,这篇文档是不可 +能完成的。 + + + +英文版维护者: Greg Kroah-Hartman <greg@kroah.com> diff --git a/Documentation/translations/zh_CN/process/index.rst b/Documentation/translations/zh_CN/process/index.rst new file mode 100644 index 000000000000..be1e764a80d2 --- /dev/null +++ b/Documentation/translations/zh_CN/process/index.rst @@ -0,0 +1,60 @@ +.. raw:: latex + + \renewcommand\thesection* + \renewcommand\thesubsection* + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/index.rst <process_index>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_process_index: + +与Linux 内核社区一起工作 +======================== + +那么你想成为Linux内核开发人员? 欢迎! 不但从技术意义上讲有很多关于内核的知识 +需要学,而且了解我们社区的工作方式也很重要。 阅读这些文章可以让您以更轻松地, +麻烦最少的方式将更改合并到内核。 + +以下是每位开发人员应阅读的基本指南。 + +.. toctree:: + :maxdepth: 1 + + howto + code-of-conduct + code-of-conduct-interpretation + submitting-patches + programming-language + coding-style + development-process + email-clients + license-rules + +其它大多数开发人员感兴趣的社区指南: + + +.. toctree:: + :maxdepth: 1 + + submitting-drivers + submit-checklist + stable-api-nonsense + stable-kernel-rules + management-style + +这些是一些总体技术指南,由于缺乏更好的地方,现在已经放在这里 + +.. toctree:: + :maxdepth: 1 + + magic-number + volatile-considered-harmful + +.. only:: subproject and html + + 目录 + ==== + + * :ref:`genindex` diff --git a/Documentation/translations/zh_CN/process/license-rules.rst b/Documentation/translations/zh_CN/process/license-rules.rst new file mode 100644 index 000000000000..30c272b2a292 --- /dev/null +++ b/Documentation/translations/zh_CN/process/license-rules.rst @@ -0,0 +1,370 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/license-rules.rst <kernel_licensing>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_kernel_licensing: + +Linux内核许可规则 +================= + +Linux内核根据LICENSES/preferred/GPL-2.0中提供的GNU通用公共许可证版本2 +(GPL-2.0)的条款提供,并在LICENSES/exceptions/Linux-syscall-note中显式 +描述了例外的系统调用,如COPYING文件中所述。 + +此文档文件提供了如何对每个源文件进行注释以使其许可证清晰明确的说明。 +它不会取代内核的许可证。 + +内核源代码作为一个整体适用于COPYING文件中描述的许可证,但是单个源文件可以 +具有不同的与GPL-20兼容的许可证:: + + GPL-1.0+ : GNU通用公共许可证v1.0或更高版本 + GPL-2.0+ : GNU通用公共许可证v2.0或更高版本 + LGPL-2.0 : 仅限GNU库通用公共许可证v2 + LGPL-2.0+: GNU 库通用公共许可证v2或更高版本 + LGPL-2.1 : 仅限GNU宽通用公共许可证v2.1 + LGPL-2.1+: GNU宽通用公共许可证v2.1或更高版本 + +除此之外,个人文件可以在双重许可下提供,例如一个兼容的GPL变体,或者BSD, +MIT等许可。 + +用户空间API(UAPI)头文件描述了用户空间程序与内核的接口,这是一种特殊情况。 +根据内核COPYING文件中的注释,syscall接口是一个明确的边界,它不会将GPL要求 +扩展到任何使用它与内核通信的软件。由于UAPI头文件必须包含在创建在Linux内核 +上运行的可执行文件的任何源文件中,因此此例外必须记录在特别的许可证表述中。 + +表达源文件许可证的常用方法是将匹配的样板文本添加到文件的顶部注释中。由于 +格式,拼写错误等,这些“样板”很难通过那些在上下文中使用的验证许可证合规性 +的工具。 + +样板文本的替代方法是在每个源文件中使用软件包数据交换(SPDX)许可证标识符。 +SPDX许可证标识符是机器可解析的,并且是用于提供文件内容的许可证的精确缩写。 +SPDX许可证标识符由Linux 基金会的SPDX 工作组管理,并得到了整个行业,工具 +供应商和法律团队的合作伙伴的一致同意。有关详细信息,请参阅 +https://spdx.org/ + +Linux内核需要所有源文件中的精确SPDX标识符。内核中使用的有效标识符在 +`许可标识符`_ 一节中进行了解释,并且已可以在 +https://spdx.org/licenses/ 上的官方SPDX许可证列表中检索,并附带许可证 +文本。 + +许可标识符语法 +-------------- + +1.安置: + + 内核文件中的SPDX许可证标识符应添加到可包含注释的文件中的第一行。对于大多 + 数文件,这是第一行,除了那些在第一行中需要'#!PATH_TO_INTERPRETER'的脚本。 + 对于这些脚本,SPDX标识符进入第二行。 + +| + +2. 风格: + + SPDX许可证标识符以注释的形式添加。注释样式取决于文件类型:: + + C source: // SPDX-License-Identifier: <SPDX License Expression> + C header: /* SPDX-License-Identifier: <SPDX License Expression> */ + ASM: /* SPDX-License-Identifier: <SPDX License Expression> */ + scripts: # SPDX-License-Identifier: <SPDX License Expression> + .rst: .. SPDX-License-Identifier: <SPDX License Expression> + .dts{i}: // SPDX-License-Identifier: <SPDX License Expression> + + 如果特定工具无法处理标准注释样式,则应使用工具接受的相应注释机制。这是在 + C 头文件中使用“/\*\*/”样式注释的原因。过去在使用生成的.lds文件中观察到 + 构建被破坏,其中'ld'无法解析C++注释。现在已经解决了这个问题,但仍然有较 + 旧的汇编程序工具无法处理C++样式的注释。 + +| + +3. 句法: + + <SPDX许可证表达式>是SPDX许可证列表中的SPDX短格式许可证标识符,或者在许可 + 证例外适用时由“WITH”分隔的两个SPDX短格式许可证标识符的组合。当应用多个许 + 可证时,表达式由分隔子表达式的关键字“AND”,“OR”组成,并由“(”,“)”包围。 + + 带有“或更高”选项的[L]GPL等许可证的许可证标识符通过使用“+”来表示“或更高” + 选项来构建。:: + + // SPDX-License-Identifier: GPL-2.0+ + // SPDX-License-Identifier: LGPL-2.1+ + + 当需要修正的许可证时,应使用WITH。 例如,linux内核UAPI文件使用表达式:: + + // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note + // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note + + 其它在内核中使用WITH例外的事例如下:: + + // SPDX-License-Identifier: GPL-2.0 WITH mif-exception + // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0 + + 例外只能与特定的许可证标识符一起使用。有效的许可证标识符列在异常文本文件 + 的标记中。有关详细信息,请参阅 `许可标识符`_ 一章中的 `例外`_ 。 + + 如果文件是双重许可且只选择一个许可证,则应使用OR。例如,一些dtsi文件在双 + 许可下可用:: + + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + + 内核中双许可文件中许可表达式的示例:: + + // SPDX-License-Identifier: GPL-2.0 OR MIT + // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause + // SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 + // SPDX-License-Identifier: GPL-2.0 OR MPL-1.1 + // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT + // SPDX-License-Identifier: GPL-1.0+ OR BSD-3-Clause OR OpenSSL + + 如果文件具有多个许可证,其条款全部适用于使用该文件,则应使用AND。例如, + 如果代码是从另一个项目继承的,并且已经授予了将其放入内核的权限,但原始 + 许可条款需要保持有效:: + + // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT + + 另一个需要遵守两套许可条款的例子是:: + + // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+ + +许可标识符 +---------- + +当前使用的许可证以及添加到内核的代码许可证可以分解为: + +1. _`优先许可`: + + 应尽可能使用这些许可证,因为它们已知完全兼容并广泛使用。这些许可证在内核 + 目录:: + + LICENSES/preferred/ + + 此目录中的文件包含完整的许可证文本和 `元标记`_ 。文件名与SPDX许可证标识 + 符相同,后者应用于源文件中的许可证。 + + 例如:: + + LICENSES/preferred/GPL-2.0 + + 包含GPLv2许可证文本和所需的元标签:: + + LICENSES/preferred/MIT + + 包含MIT许可证文本和所需的元标记 + + _`元标记`: + + 许可证文件中必须包含以下元标记: + + - Valid-License-Identifier: + + 一行或多行, 声明那些许可标识符在项目内有效, 以引用此特定许可的文本。通 + 常这是一个有效的标识符,但是例如对于带有'或更高'选项的许可证,两个标识 + 符都有效。 + + - SPDX-URL: + + SPDX页面的URL,其中包含与许可证相关的其他信息. + + - Usage-Guidance: + + 使用建议的自由格式文本。该文本必须包含SPDX许可证标识符的正确示例,因为 + 它们应根据 `许可标识符语法`_ 指南放入源文件中。 + + - License-Text: + + 此标记之后的所有文本都被视为原始许可文本 + + 文件格式示例:: + + Valid-License-Identifier: GPL-2.0 + Valid-License-Identifier: GPL-2.0+ + SPDX-URL: https://spdx.org/licenses/GPL-2.0.html + Usage-Guide: + To use this license in source code, put one of the following SPDX + tag/value pairs into a comment according to the placement + guidelines in the licensing rules documentation. + For 'GNU General Public License (GPL) version 2 only' use: + SPDX-License-Identifier: GPL-2.0 + For 'GNU General Public License (GPL) version 2 or any later version' use: + SPDX-License-Identifier: GPL-2.0+ + License-Text: + Full license text + + :: + + SPDX-License-Identifier: MIT + SPDX-URL: https://spdx.org/licenses/MIT.html + Usage-Guide: + To use this license in source code, put the following SPDX + tag/value pair into a comment according to the placement + guidelines in the licensing rules documentation. + SPDX-License-Identifier: MIT + License-Text: + Full license text + +| + +2. 不推荐的许可证: + + 这些许可证只应用于现有代码或从其他项目导入代码。这些许可证在内核目录:: + + LICENSES/other/ + + 此目录中的文件包含完整的许可证文本和 `元标记`_ 。文件名与SPDX许可证标识 + 符相同,后者应用于源文件中的许可证。 + + 例如:: + + LICENSES/other/ISC + + 包含国际系统联合许可文本和所需的元标签:: + + LICENSES/other/ZLib + + 包含ZLIB许可文本和所需的元标签. + + 元标签: + + “其他”许可证的元标签要求与 `优先许可`_ 的要求相同。 + + 文件格式示例:: + + Valid-License-Identifier: ISC + SPDX-URL: https://spdx.org/licenses/ISC.html + Usage-Guide: + Usage of this license in the kernel for new code is discouraged + and it should solely be used for importing code from an already + existing project. + To use this license in source code, put the following SPDX + tag/value pair into a comment according to the placement + guidelines in the licensing rules documentation. + SPDX-License-Identifier: ISC + License-Text: + Full license text + +| + +3. _`例外`: + + 某些许可证可以修改,并允许原始许可证不具有的某些例外权利。这些例外在 + 内核目录:: + + LICENSES/exceptions/ + + 此目录中的文件包含完整的例外文本和所需的 `例外元标记`_ 。 + + 例如:: + + LICENSES/exceptions/Linux-syscall-note + + 包含Linux内核的COPYING文件中记录的Linux系统调用例外,该文件用于UAPI + 头文件。例如:: + + LICENSES/exceptions/GCC-exception-2.0 + + 包含GCC'链接例外',它允许独立于其许可证的任何二进制文件与标记有此例外的 + 文件的编译版本链接。这是从GPL不兼容源代码创建可运行的可执行文件所必需的。 + + _`例外元标记`: + + 以下元标记必须在例外文件中可用: + + - SPDX-Exception-Identifier: + + 一个可与SPDX许可证标识符一起使用的例外标识符。 + + - SPDX-URL: + + SPDX页面的URL,其中包含与例外相关的其他信息。 + + - SPDX-Licenses: + + 以逗号分隔的例外可用的SPDX许可证标识符列表。 + + - Usage-Guidance: + + 使用建议的自由格式文本。必须在文本后面加上SPDX许可证标识符的正确示例, + 因为它们应根据 `许可标识符语法`_ 指南放入源文件中。 + + - Exception-Text: + + 此标记之后的所有文本都被视为原始异常文本 + + 文件格式示例:: + + SPDX-Exception-Identifier: Linux-syscall-note + SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html + SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+ + Usage-Guidance: + This exception is used together with one of the above SPDX-Licenses + to mark user-space API (uapi) header files so they can be included + into non GPL compliant user-space application code. + To use this exception add it with the keyword WITH to one of the + identifiers in the SPDX-Licenses tag: + SPDX-License-Identifier: <SPDX-License> WITH Linux-syscall-note + Exception-Text: + Full exception text + + :: + + SPDX-Exception-Identifier: GCC-exception-2.0 + SPDX-URL: https://spdx.org/licenses/GCC-exception-2.0.html + SPDX-Licenses: GPL-2.0, GPL-2.0+ + Usage-Guidance: + The "GCC Runtime Library exception 2.0" is used together with one + of the above SPDX-Licenses for code imported from the GCC runtime + library. + To use this exception add it with the keyword WITH to one of the + identifiers in the SPDX-Licenses tag: + SPDX-License-Identifier: <SPDX-License> WITH GCC-exception-2.0 + Exception-Text: + Full exception text + + +所有SPDX许可证标识符和例外都必须在LICENSES子目录中具有相应的文件。这是允许 +工具验证(例如checkpatch.pl)以及准备好从源读取和提取许可证所必需的, 这是 +各种FOSS组织推荐的,例如 `FSFE REUSE initiative <https://reuse.software/>`_. + +_`模块许可` +----------------- + + 可加载内核模块还需要MODULE_LICENSE()标记。此标记既不替代正确的源代码 + 许可证信息(SPDX-License-Identifier),也不以任何方式表示或确定提供模块 + 源代码的确切许可证。 + + 此标记的唯一目的是提供足够的信息,该模块是否是自由软件或者是内核模块加 + 载器和用户空间工具的专有模块。 + + MODULE_LICENSE()的有效许可证字符串是: + + ============================= ============================================= + "GPL" 模块是根据GPL版本2许可的。这并不表示仅限于 + GPL-2.0或GPL-2.0或更高版本之间的任何区别。 + 最正确许可证信息只能通过相应源文件中的许可证 + 信息来确定 + + "GPL v2" 和"GPL"相同,它的存在是因为历史原因。 + + "GPL and additional rights" 表示模块源在GPL v2变体和MIT许可下双重许可的 + 历史变体。请不要在新代码中使用。 + + "Dual MIT/GPL" 表达该模块在GPL v2变体或MIT许可证选择下双重 + 许可的正确方式。 + + "Dual BSD/GPL" 该模块根据GPL v2变体或BSD许可证选择进行双重 + 许可。 BSD许可证的确切变体只能通过相应源文件 + 中的许可证信息来确定。 + + "Dual MPL/GPL" 该模块根据GPL v2变体或Mozilla Public License + (MPL)选项进行双重许可。 MPL许可证的确切变体 + 只能通过相应的源文件中的许可证信息来确定。 + + "Proprietary" 该模块属于专有许可。此字符串仅用于专有的第三 + 方模块,不能用于在内核树中具有源代码的模块。 + 以这种方式标记的模块在加载时会使用'P'标记污 + 染内核,并且内核模块加载器拒绝将这些模块链接 + 到使用EXPORT_SYMBOL_GPL()导出的符号。 + ============================= ============================================= + diff --git a/Documentation/translations/zh_CN/process/magic-number.rst b/Documentation/translations/zh_CN/process/magic-number.rst new file mode 100644 index 000000000000..15c592518194 --- /dev/null +++ b/Documentation/translations/zh_CN/process/magic-number.rst @@ -0,0 +1,151 @@ +.. _cn_magicnumbers: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/magic-number.rst <magicnumbers>` + +如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可 +以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者:: + + 中文版维护者: 贾威威 Jia Wei Wei <harryxiyou@gmail.com> + 中文版翻译者: 贾威威 Jia Wei Wei <harryxiyou@gmail.com> + 中文版校译者: 贾威威 Jia Wei Wei <harryxiyou@gmail.com> + +Linux 魔术数 +============ + +这个文件是有关当前使用的魔术值注册表。当你给一个结构添加了一个魔术值,你也应该把这个魔术值添加到这个文件,因为我们最好把用于各种结构的魔术值统一起来。 + +使用魔术值来保护内核数据结构是一个非常好的主意。这就允许你在运行期检查(a)一个结构是否已经被攻击,或者(b)你已经给一个例行程序通过了一个错误的结构。后一种情况特别地有用---特别是当你通过一个空指针指向结构体的时候。tty源码,例如,经常通过特定驱动使用这种方法并且反复地排列特定方面的结构。 + +使用魔术值的方法是在结构的开始处声明的,如下:: + + struct tty_ldisc { + int magic; + ... + }; + +当你以后给内核添加增强功能的时候,请遵守这条规则!这样就会节省数不清的调试时间,特别是一些古怪的情况,例如,数组超出范围并且重新写了超出部分。遵守这个规则,这些情况可以被快速地,安全地避免。 + + Theodore Ts'o + 31 Mar 94 + +给当前的Linux 2.1.55添加魔术表。 + + Michael Chastain + <mailto:mec@shout.net> + 22 Sep 1997 + +现在应该最新的Linux 2.1.112.因为在特性冻结期间,不能在2.2.x前改变任何东西。这些条目被数域所排序。 + + Krzysztof G.Baranowski + <mailto: kgb@knm.org.pl> + 29 Jul 1998 + +更新魔术表到Linux 2.5.45。刚好越过特性冻结,但是有可能还会有一些新的魔术值在2.6.x之前融入到内核中。 + + Petr Baudis + <pasky@ucw.cz> + 03 Nov 2002 + +更新魔术表到Linux 2.5.74。 + + Fabian Frederick + <ffrederick@users.sourceforge.net> + 09 Jul 2003 + +===================== ================ ======================== ========================================== +魔术数名 数字 结构 文件 +===================== ================ ======================== ========================================== +PG_MAGIC 'P' pg_{read,write}_hdr ``include/linux/pg.h`` +CMAGIC 0x0111 user ``include/linux/a.out.h`` +MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h`` +HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c`` +APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` +CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h`` +DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c`` +DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c`` +FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` +FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c`` +ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h`` +PTY_MAGIC 0x5001 ``drivers/char/pty.c`` +PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h`` +SERIAL_MAGIC 0x5301 async_struct ``include/linux/serial.h`` +SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h`` +SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h`` +STRIP_MAGIC 0x5303 strip ``drivers/net/strip.c`` +X25_ASY_MAGIC 0x5303 x25_asy ``drivers/net/x25_asy.h`` +SIXPACK_MAGIC 0x5304 sixpack ``drivers/net/hamradio/6pack.h`` +AX25_MAGIC 0x5316 ax_disp ``drivers/net/mkiss.h`` +TTY_MAGIC 0x5401 tty_struct ``include/linux/tty.h`` +MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c`` +TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h`` +MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c`` +TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h`` +USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h`` +FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c`` +USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c`` +RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c`` +USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h`` +CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h`` +RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h`` +LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c`` +GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h`` +RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c`` +NBD_REQUEST_MAGIC 0x12560953 nbd_request ``include/linux/nbd.h`` +RED_MAGIC2 0x170fc2a5 (any) ``mm/slab.c`` +BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c`` +ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h`` +ECP_MAGIC 0x21504345 cdkecpsig ``include/linux/cdk.h`` +LSOMAGIC 0x27091997 lso ``drivers/fc4/fc.c`` +LSMAGIC 0x2a3b4d2a ls ``drivers/fc4/fc.c`` +WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} ``include/linux/wanpipe.h`` +CS_CARD_MAGIC 0x43525553 cs_card ``sound/oss/cs46xx.c`` +LABELCL_MAGIC 0x4857434c labelcl_info_s ``include/asm/ia64/sn/labelcl.h`` +ISDN_ASYNC_MAGIC 0x49344C01 modem_info ``include/linux/isdn.h`` +CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info ``drivers/s390/net/ctctty.c`` +ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s ``drivers/isdn/i4l/isdn_net_lib.h`` +SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg ``arch/*/amiga/config.c`` +CS_STATE_MAGIC 0x4c4f4749 cs_state ``sound/oss/cs46xx.c`` +SLAB_C_MAGIC 0x4f17a36d kmem_cache ``mm/slab.c`` +COW_MAGIC 0x4f4f4f4d cow_header_v1 ``arch/um/drivers/ubd_user.c`` +I810_CARD_MAGIC 0x5072696E i810_card ``sound/oss/i810_audio.c`` +TRIDENT_CARD_MAGIC 0x5072696E trident_card ``sound/oss/trident.c`` +ROUTER_MAGIC 0x524d4157 wan_device [in ``wanrouter.h`` pre 3.9] +SAVEKMSG_MAGIC1 0x53415645 savekmsg ``arch/*/amiga/config.c`` +GDA_MAGIC 0x58464552 gda ``arch/mips/include/asm/sn/gda.h`` +RED_MAGIC1 0x5a2cf071 (any) ``mm/slab.c`` +EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev ``drivers/atm/lanai.c`` +HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` +PCXX_MAGIC 0x5c6df104 channel ``drivers/char/pcxx.h`` +KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` +I810_STATE_MAGIC 0x63657373 i810_state ``sound/oss/i810_audio.c`` +TRIDENT_STATE_MAGIC 0x63657373 trient_state ``sound/oss/trident.c`` +M3_CARD_MAGIC 0x646e6f50 m3_card ``sound/oss/maestro3.c`` +FW_HEADER_MAGIC 0x65726F66 fw_header ``drivers/atm/fore200e.h`` +SLOT_MAGIC 0x67267321 slot ``drivers/hotplug/cpqphp.h`` +SLOT_MAGIC 0x67267322 slot ``drivers/hotplug/acpiphp.h`` +LO_MAGIC 0x68797548 nbd_device ``include/linux/nbd.h`` +OPROFILE_MAGIC 0x6f70726f super_block ``drivers/oprofile/oprofilefs.h`` +M3_STATE_MAGIC 0x734d724d m3_state ``sound/oss/maestro3.c`` +VMALLOC_MAGIC 0x87654320 snd_alloc_track ``sound/core/memory.c`` +KMALLOC_MAGIC 0x87654321 snd_alloc_track ``sound/core/memory.c`` +PWC_MAGIC 0x89DC10AB pwc_device ``drivers/usb/media/pwc.h`` +NBD_REPLY_MAGIC 0x96744668 nbd_reply ``include/linux/nbd.h`` +ENI155_MAGIC 0xa54b872d midway_eprom ``drivers/atm/eni.h`` +CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.h`` +DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram ``drivers/scsi/gdth.h`` +YAM_MAGIC 0xF10A7654 yam_port ``drivers/net/hamradio/yam.c`` +CCB_MAGIC 0xf2691ad2 ccb ``drivers/scsi/ncr53c8xx.c`` +QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry ``drivers/scsi/arm/queue.c`` +QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry ``drivers/scsi/arm/queue.c`` +HTB_CMAGIC 0xFEFAFEF1 htb_class ``net/sched/sch_htb.c`` +NMI_MAGIC 0x48414d4d455201 nmi_s ``arch/mips/include/asm/sn/nmi.h`` +===================== ================ ======================== ========================================== + + +请注意,在声音记忆管理中仍然有一些特殊的为每个驱动定义的魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。 + +IrDA子系统也使用了大量的自己的魔术值,查看include/net/irda/irda.h来获取他们完整的信息。 + +HFS是另外一个比较大的使用魔术值的文件系统-你可以在fs/hfs/hfs.h中找到他们。 diff --git a/Documentation/translations/zh_CN/process/management-style.rst b/Documentation/translations/zh_CN/process/management-style.rst new file mode 100644 index 000000000000..a181fa56d19e --- /dev/null +++ b/Documentation/translations/zh_CN/process/management-style.rst @@ -0,0 +1,207 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/management-style.rst <managementstyle>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_managementstyle: + +Linux内核管理风格 +================= + +这是一个简短的文档,描述了Linux内核首选的(或胡编的,取决于您问谁)管理风格。 +它的目的是在某种程度上参照 :ref:`process/coding-style.rst <codingstyle>` +主要是为了避免反复回答 [#cnf1]_ 相同(或类似)的问题。 + +管理风格是非常个人化的,比简单的编码风格规则更难以量化,因此本文档可能与实 +际情况有关,也可能与实际情况无关。起初它是一个玩笑,但这并不意味着它可能不 +是真的。你得自己决定。 + +顺便说一句,在谈到“核心管理者”时,主要是技术负责人,而不是在公司内部进行传 +统管理的人。如果你签署了采购订单或者对你的团队的预算有任何了解,你几乎肯定 +不是一个核心管理者。这些建议可能适用于您,也可能不适用于您。 + +首先,我建议你购买“高效人的七个习惯”,而不是阅读它。烧了它,这是一个伟大的 +象征性姿态。 + +.. [#cnf1] 本文件并不是通过回答问题,而是通过让提问者痛苦地明白,我们不知道 + 答案是什么。 + +不管怎样,这里是: + +.. _decisions: + +1)决策 +------- + +每个人都认为管理者做决定,而且决策很重要。决定越大越痛苦,管理者就必须越高级。 +这很明显,但事实并非如此。 + +游戏的名字是 **避免** 做出决定。尤其是,如果有人告诉你“选择(a)或(b), +我们真的需要你来做决定”,你就是陷入麻烦的管理者。你管理的人比你更了解细节, +所以如果他们来找你做技术决策,你完蛋了。你显然没有能力为他们做这个决定。 + +(推论:如果你管理的人不比你更了解细节,你也会被搞砸,尽管原因完全不同。 +也就是说,你的工作是错的,他们应该管理你的才智) + +所以游戏的名字是 **避免** 做出决定,至少是那些大而痛苦的决定。做一些小的 +和非结果性的决定是很好的,并且使您看起来好像知道自己在做什么,所以内核管理者 +需要做的是将那些大的和痛苦的决定变成那些没有人真正关心的小事情。 + +这有助于认识到一个大的决定和一个小的决定之间的关键区别是你是否可以在事后修正 +你的决定。任何决定都可以通过始终确保如果你错了(而且你一定会错),你以后总是 +可以通过回溯来弥补损失。突然间,你就要做两个无关紧要的决定,一个是错误的,另 +一个是正确的。 + +人们甚至会认为这是真正的领导能力(咳,胡说,咳)。 + +因此,避免重大决策的关键在于避免做那些无法挽回的事情。不要被引导到一个你无法 +逃离的角落。走投无路的老鼠可能很危险——走投无路的管理者真可怜。 + +事实证明,由于没有人会愚蠢到让内核管理者承担巨大的财政责任,所以通常很容易 +回溯。既然你不可能浪费掉你无法偿还的巨额资金,你唯一可以回溯的就是技术决策, +而回溯很容易:只要告诉大家你是个不称职的傻瓜,说对不起,然后撤销你去年让别 +人所做的毫无价值的工作。突然间,你一年前做的决定不在是一个重大的决定,因为 +它很容易被推翻。 + +事实证明,有些人对接受这种方法有困难,原因有两个: + + - 承认你是个白痴比看起来更难。我们都喜欢保持形象,在公共场合说你错了有时 + 确实很难。 + - 如果有人告诉你,你去年所做的工作终究是不值得的,那么对那些可怜的低级工 + 程师来说也是很困难的,虽然实际的 **工作** 很容易删除,但你可能已经不可 + 挽回地失去了工程师的信任。记住:“不可撤销”是我们一开始就试图避免的, + 而你的决定终究是一个重大的决定。 + +令人欣慰的是,这两个原因都可以通过预先承认你没有任何线索,提前告诉人们你的 +决定完全是初步的,而且可能是错误的事情来有效地缓解。你应该始终保留改变主意 +的权利,并让人们 **意识** 到这一点。当你 **还没有** 做过真正愚蠢的事情的时 +候,承认自己是愚蠢的要容易得多。 + +然后,当它真的被证明是愚蠢的时候,人们就转动他们的眼珠说“哎呀,下次不要了”。 + +这种对不称职的先发制人的承认,也可能使真正做这项工作的人也会三思是否值得做。 +毕竟,如果他们不确定这是否是一个好主意,你肯定不应该通过向他们保证他们所做 +的工作将会进入(内核)鼓励他们。在他们开始一项巨大的努力之前,至少让他们三 +思而后行。 + +记住:他们最好比你更了解细节,而且他们通常认为他们对每件事都有答案。作为一 +个管理者,你能做的最好的事情不是灌输自信,而是对他们所做的事情进行健康的批 +判性思考。 + +顺便说一句,另一种避免做出决定的方法是看起来很可怜的抱怨 “我们不能两者兼 +得吗?” 相信我,它是有效的。如果不清楚哪种方法更好,他们最终会弄清楚的。 +最终的答案可能是两个团队都会因为这种情况而感到沮丧,以至于他们放弃了。 + +这听起来像是一个失败,但这通常是一个迹象,表明两个项目都有问题,而参与其中 +的人不能做决定的原因是他们都是错误的。你最终会闻到玫瑰的味道,你避免了另一 +个你本可以搞砸的决定。 + +2)人 +----- + +大多数人都是白痴,做一名管理者意味着你必须处理好这件事,也许更重要的是, +**他们** 必须处理好你。 + +事实证明,虽然很容易纠正技术错误,但不容易纠正人格障碍。你只能和他们的和 +你的(人格障碍)共处。 + +但是,为了做好作为内核管理者的准备,最好记住不要烧掉任何桥梁,不要轰炸任何 +无辜的村民,也不要疏远太多的内核开发人员。事实证明,疏远人是相当容易的,而 +亲近一个疏远的人是很难的。因此,“疏远”立即属于“不可逆”的范畴,并根据 +:ref:`decisions` 成为绝不可以做的事情。 + +这里只有几个简单的规则: + + (1) 不要叫人笨蛋(至少不要在公共场合) + (2) 学习如何在忘记规则(1)时道歉 + +问题在于 #1 很容易去做,因为你可以用数百万种不同的方式说“你是一个笨蛋” [#cnf2]_ +有时甚至没有意识到,而且几乎总是带着一种白热化的信念,认为你是对的。 + +你越确信自己是对的(让我们面对现实吧,你可以把几乎所有人都称为坏人,而且你 +经常是对的),事后道歉就越难。 + +要解决此问题,您实际上只有两个选项: + + - 非常擅长道歉 + - 把“爱”均匀地散开,没有人会真正感觉到自己被不公平地瞄准了。让它有足够的 + 创造性,他们甚至可能会觉得好笑。 + +选择永远保持礼貌是不存在的。没有人会相信一个如此明显地隐藏了他们真实性格的人。 + +.. [#cnf2] 保罗·西蒙演唱了“离开爱人的50种方法”,因为坦率地说,“告诉开发者 + 他们是D*CKHEAD" 的100万种方法都无法确认。但我确信他已经这么想了。 + +3)人2 - 好人 +------------- + +虽然大多数人都是白痴,但不幸的是,据此推论你也是白痴,尽管我们都自我感觉良 +好,我们比普通人更好(让我们面对现实吧,没有人相信他们是普通人或低于普通人), +我们也应该承认我们不是最锋利的刀,而且会有其他人比你更不像白痴。 + +有些人对聪明人反应不好。其他人利用它们。 + +作为内核维护人员,确保您在第二组中。接受他们,因为他们会让你的工作更容易。 +特别是,他们能够为你做决定,这就是游戏的全部内容。 + +所以当你发现一个比你聪明的人时,就顺其自然吧。你的管理职责在很大程度上变成 +了“听起来像是个好主意——去尝试吧”,或者“听起来不错,但是XXX呢?”“。第二个版 +本尤其是一个很好的方法,要么学习一些关于“XXX”的新东西,要么通过指出一些聪明 +人没有想到的东西来显得更具管理性。无论哪种情况,你都会赢。 + +要注意的一件事是认识到一个领域的伟大不一定会转化为其他领域。所以你可能会向 +特定的方向刺激人们,但让我们面对现实吧,他们可能擅长他们所做的事情,而且对 +其他事情都很差劲。好消息是,人们往往会自然而然地重拾他们擅长的东西,所以当 +你向某个方向刺激他们时,你并不是在做不可逆转的事情,只是不要用力推。 + +4)责备 +------- + +事情会出问题的,人们希望去责备人。贴标签,你就是受责备的人。 + +事实上,接受责备并不难,尤其是当人们意识到这不 **全是** 你的过错时。这让我 +们找到了承担责任的最佳方式:为别人承担这件事。你会感觉很好,他们会感觉很好, +没有受到指责. 那谁,失去了他们的全部36GB色情收藏的人,因为你的无能将勉强承 +认,你至少没有试图逃避责任。 + +然后让真正搞砸了的开发人员(如果你能找到他们)私下知道他们搞砸了。不仅是为 +了将来可以避免,而且为了让他们知道他们欠你一个人情。而且,也许更重要的是, +他们也可能是能够解决问题的人。因为,让我们面对现实吧,肯定不是你。 + +承担责任也是你首先成为管理者的原因。这是让人们信任你,让你获得潜在的荣耀的 +一部分,因为你就是那个会说“我搞砸了”的人。如果你已经遵循了以前的规则,你现 +在已经很擅长说了。 + +5)应避免的事情 +--------------- + +有一件事人们甚至比被称为“笨蛋”更讨厌,那就是在一个神圣的声音中被称为“笨蛋”。 +第一个你可以道歉,第二个你不会真正得到机会。即使你做得很好,他们也可能不再 +倾听。 + +我们都认为自己比别人强,这意味着当别人装腔作势时,这会让我们很恼火。你也许 +在道德和智力上比你周围的每个人都优越,但不要试图太明显,除非你真的打算激怒 +某人 [#cnf3]_ + +同样,不要对事情太客气或太微妙。礼貌很容易落得落花流水,把问题隐藏起来, +正如他们所说,“在互联网上,没人能听到你的含蓄。”用一个钝器把这一点锤进去, +因为你不能真的依靠别人来获得你的观点。 + +一些幽默可以帮助缓和直率和道德化。过度到荒谬的地步,可以灌输一个观点,而不 +会让接受者感到痛苦,他们只是认为你是愚蠢的。因此,它可以帮助我们摆脱对批评 +的个人心理障碍。 + +.. [#cnf3] 提示:与你的工作没有直接关系的网络新闻组是消除你对他人不满的好 + 方法。偶尔写些侮辱性的帖子,打个喷嚏,让你的情绪得到净化。别把牢骚带回家 + +6)为什么是我? +--------------- + +既然你的主要责任似乎是为别人的错误承担责任,并且让别人痛苦地明白你是不称职 +的,那么显而易见的问题之一就变成了为什么首先要这样做。 + +首先,虽然你可能会或可能不会听到十几岁女孩(或男孩,让我们不要在这里评判或 +性别歧视)敲你的更衣室门,你会得到一个巨大的个人成就感为“负责”。别介意你真 +的在领导别人,你要跟上别人,尽可能快地追赶他们。每个人都会认为你是负责人。 + +如果你可以做到这个, 这是个伟大的工作! diff --git a/Documentation/translations/zh_CN/process/programming-language.rst b/Documentation/translations/zh_CN/process/programming-language.rst new file mode 100644 index 000000000000..51fd4ef48ea1 --- /dev/null +++ b/Documentation/translations/zh_CN/process/programming-language.rst @@ -0,0 +1,41 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/programming-language.rst <programming_language>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_programming_language: + +程序设计语言 +============ + +内核是用C语言 [c-language]_ 编写的。更准确地说,内核通常是用 ``gcc`` [gcc]_ +在 ``-std=gnu89`` [gcc-c-dialect-options]_ 下编译的:ISO C90的 GNU 方言( +包括一些C99特性) + +这种方言包含对语言 [gnu-extensions]_ 的许多扩展,当然,它们许多都在内核中使用。 + +对于一些体系结构,有一些使用 ``clang`` [clang]_ 和 ``icc`` [icc]_ 编译内核 +的支持,尽管在编写此文档时还没有完成,仍需要第三方补丁。 + +属性 +---- + +在整个内核中使用的一个常见扩展是属性(attributes) [gcc-attribute-syntax]_ +属性允许将实现定义的语义引入语言实体(如变量、函数或类型),而无需对语言进行 +重大的语法更改(例如添加新关键字) [n2049]_ + +在某些情况下,属性是可选的(即不支持这些属性的编译器仍然应该生成正确的代码, +即使其速度较慢或执行的编译时检查/诊断次数不够) + +内核定义了伪关键字(例如, ``pure`` ),而不是直接使用GNU属性语法(例如, +``__attribute__((__pure__))`` ),以检测可以使用哪些关键字和/或缩短代码, 具体 +请参阅 ``include/linux/compiler_attributes.h`` + +.. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards +.. [gcc] https://gcc.gnu.org +.. [clang] https://clang.llvm.org +.. [icc] https://software.intel.com/en-us/c-compilers +.. [gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html +.. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html +.. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html +.. [n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf diff --git a/Documentation/translations/zh_CN/process/stable-api-nonsense.rst b/Documentation/translations/zh_CN/process/stable-api-nonsense.rst new file mode 100644 index 000000000000..b4ddb6e88d9d --- /dev/null +++ b/Documentation/translations/zh_CN/process/stable-api-nonsense.rst @@ -0,0 +1,155 @@ +.. _cn_stable_api_nonsense: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/stable-api-nonsense.rst + <stable_api_nonsense>` + +译者:: + + 中文版维护者: 钟宇 TripleX Chung <xxx.phy@gmail.com> + 中文版翻译者: 钟宇 TripleX Chung <xxx.phy@gmail.com> + 中文版校译者: 李阳 Li Yang <leoyang.li@nxp.com> + +Linux 内核驱动接口 +================== + +写作本文档的目的,是为了解释为什么Linux既没有二进制内核接口,也没有稳定 +的内核接口。这里所说的内核接口,是指内核里的接口,而不是内核和用户空间 +的接口。内核到用户空间的接口,是提供给应用程序使用的系统调用,系统调用 +在历史上几乎没有过变化,将来也不会有变化。我有一些老应用程序是在0.9版本 +或者更早版本的内核上编译的,在使用2.6版本内核的Linux发布上依然用得很好 +。用户和应用程序作者可以将这个接口看成是稳定的。 + + +执行纲要 +-------- + +你也许以为自己想要稳定的内核接口,但是你不清楚你要的实际上不是它。你需 +要的其实是稳定的驱动程序,而你只有将驱动程序放到公版内核的源代码树里, +才有可能达到这个目的。而且这样做还有很多其它好处,正是因为这些好处使得 +Linux能成为强壮,稳定,成熟的操作系统,这也是你最开始选择Linux的原因。 + + +入门 +----- + +只有那些写驱动程序的“怪人”才会担心内核接口的改变,对广大用户来说,既 +看不到内核接口,也不需要去关心它。 + +首先,我不打算讨论关于任何非GPL许可的内核驱动的法律问题,这些非GPL许可 +的驱动程序包括不公开源代码,隐藏源代码,二进制或者是用源代码包装,或者 +是其它任何形式的不能以GPL许可公开源代码的驱动程序。如果有法律问题,请咨 +询律师,我只是一个程序员,所以我只打算探讨技术问题(不是小看法律问题, +法律问题很实际,并且需要一直关注)。 + +既然只谈技术问题,我们就有了下面两个主题:二进制内核接口和稳定的内核源 +代码接口。这两个问题是互相关联的,让我们先解决掉二进制接口的问题。 + + +二进制内核接口 +-------------- +假如我们有一个稳定的内核源代码接口,那么自然而然的,我们就拥有了稳定的 +二进制接口,是这样的吗?错。让我们看看关于Linux内核的几点事实: + + - 取决于所用的C编译器的版本,不同的内核数据结构里的结构体的对齐方 + 式会有差别,代码中不同函数的表现形式也不一样(函数是不是被inline + 编译取决于编译器行为)。不同的函数的表现形式并不重要,但是数据 + 结构内部的对齐方式很关键。 + + - 取决于内核的配置选项,不同的选项会让内核的很多东西发生改变: + + - 同一个结构体可能包含不同的成员变量 + - 有的函数可能根本不会被实现(比如编译的时候没有选择SMP支持 + 一些锁函数就会被定义成空函数)。 + - 内核使用的内存会以不同的方式对齐,这取决于不同的内核配置选 + 项。 + + - Linux可以在很多的不同体系结构的处理器上运行。在某个体系结构上编 + 译好的二进制驱动程序,不可能在另外一个体系结构上正确的运行。 + +对于一个特定的内核,满足这些条件并不难,使用同一个C编译器和同样的内核配 +置选项来编译驱动程序模块就可以了。这对于给一个特定Linux发布的特定版本提 +供驱动程序,是完全可以满足需求的。但是如果你要给不同发布的不同版本都发 +布一个驱动程序,就需要在每个发布上用不同的内核设置参数都编译一次内核, +这简直跟噩梦一样。而且还要注意到,每个Linux发布还提供不同的Linux内核, +这些内核都针对不同的硬件类型进行了优化(有很多种不同的处理器,还有不同 +的内核设置选项)。所以每发布一次驱动程序,都需要提供很多不同版本的内核 +模块。 + +相信我,如果你真的要采取这种发布方式,一定会慢慢疯掉,我很久以前就有过 +深刻的教训... + + +稳定的内核源代码接口 +-------------------- + +如果有人不将他的内核驱动程序,放入公版内核的源代码树,而又想让驱动程序 +一直保持在最新的内核中可用,那么这个话题将会变得没完没了。 +内核开发是持续而且快节奏的,从来都不会慢下来。内核开发人员在当前接口中 +找到bug,或者找到更好的实现方式。一旦发现这些,他们就很快会去修改当前的 +接口。修改接口意味着,函数名可能会改变,结构体可能被扩充或者删减,函数 +的参数也可能发生改变。一旦接口被修改,内核中使用这些接口的地方需要同时 +修正,这样才能保证所有的东西继续工作。 + +举一个例子,内核的USB驱动程序接口在USB子系统的整个生命周期中,至少经历 +了三次重写。这些重写解决以下问题: + + - 把数据流从同步模式改成非同步模式,这个改动减少了一些驱动程序的 + 复杂度,提高了所有USB驱动程序的吞吐率,这样几乎所有的USB设备都 + 能以最大速率工作了。 + - 修改了USB核心代码中为USB驱动分配数据包内存的方式,所有的驱动都 + 需要提供更多的参数给USB核心,以修正了很多已经被记录在案的死锁。 + +这和一些封闭源代码的操作系统形成鲜明的对比,在那些操作系统上,不得不额 +外的维护旧的USB接口。这导致了一个可能性,新的开发者依然会不小心使用旧的 +接口,以不恰当的方式编写代码,进而影响到操作系统的稳定性。 +在上面的例子中,所有的开发者都同意这些重要的改动,在这样的情况下修改代 +价很低。如果Linux保持一个稳定的内核源代码接口,那么就得创建一个新的接口 +;旧的,有问题的接口必须一直维护,给Linux USB开发者带来额外的工作。既然 +所有的Linux USB驱动的作者都是利用自己的时间工作,那么要求他们去做毫无意 +义的免费额外工作,是不可能的。 +安全问题对Linux来说十分重要。一个安全问题被发现,就会在短时间内得到修 +正。在很多情况下,这将导致Linux内核中的一些接口被重写,以从根本上避免安 +全问题。一旦接口被重写,所有使用这些接口的驱动程序,必须同时得到修正, +以确定安全问题已经得到修复并且不可能在未来还有同样的安全问题。如果内核 +内部接口不允许改变,那么就不可能修复这样的安全问题,也不可能确认这样的 +安全问题以后不会发生。 +开发者一直在清理内核接口。如果一个接口没有人在使用了,它就会被删除。这 +样可以确保内核尽可能的小,而且所有潜在的接口都会得到尽可能完整的测试 +(没有人使用的接口是不可能得到良好的测试的)。 + + +要做什么 +-------- + +如果你写了一个Linux内核驱动,但是它还不在Linux源代码树里,作为一个开发 +者,你应该怎么做?为每个发布的每个版本提供一个二进制驱动,那简直是一个 +噩梦,要跟上永远处于变化之中的内核接口,也是一件辛苦活。 +很简单,让你的驱动进入内核源代码树(要记得我们在谈论的是以GPL许可发行 +的驱动,如果你的代码不符合GPL,那么祝你好运,你只能自己解决这个问题了, +你这个吸血鬼<把Andrew和Linus对吸血鬼的定义链接到这里>)。当你的代码加入 +公版内核源代码树之后,如果一个内核接口改变,你的驱动会直接被修改接口的 +那个人修改。保证你的驱动永远都可以编译通过,并且一直工作,你几乎不需要 +做什么事情。 + +把驱动放到内核源代码树里会有很多的好处: + + - 驱动的质量会提升,而维护成本(对原始作者来说)会下降。 + - 其他人会给驱动添加新特性。 + - 其他人会找到驱动中的bug并修复。 + - 其他人会在驱动中找到性能优化的机会。 + - 当外部的接口的改变需要修改驱动程序的时候,其他人会修改驱动程序 + - 不需要联系任何发行商,这个驱动会自动的随着所有的Linux发布一起发 + 布。 + +和别的操作系统相比,Linux为更多不同的设备提供现成的驱动,而且能在更多不 +同体系结构的处理器上支持这些设备。这个经过考验的开发模式,必然是错不了 +的 :) + +感谢 +---- +感谢 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder, +Robert Love, and Nishanth Aravamudan 对于本文档早期版本的评审和建议。 + +英文版维护者: Greg Kroah-Hartman <greg@kroah.com> diff --git a/Documentation/translations/zh_CN/process/stable-kernel-rules.rst b/Documentation/translations/zh_CN/process/stable-kernel-rules.rst new file mode 100644 index 000000000000..fba361f2ddfd --- /dev/null +++ b/Documentation/translations/zh_CN/process/stable-kernel-rules.rst @@ -0,0 +1,64 @@ +.. _cn_stable_kernel_rules: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>` + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者:: + + 中文版维护者: 钟宇 TripleX Chung <xxx.phy@gmail.com> + 中文版翻译者: 钟宇 TripleX Chung <xxx.phy@gmail.com> + 中文版校译者: + - 李阳 Li Yang <leoyang.li@nxp.com> + - Kangkai Yin <e12051@motorola.com> + +所有你想知道的事情 - 关于linux稳定版发布 +======================================== + +关于Linux 2.6稳定版发布,所有你想知道的事情。 + +关于哪些类型的补丁可以被接收进入稳定版代码树,哪些不可以的规则: +---------------------------------------------------------------- + + - 必须是显而易见的正确,并且经过测试的。 + - 连同上下文,不能大于100行。 + - 必须只修正一件事情。 + - 必须修正了一个给大家带来麻烦的真正的bug(不是“这也许是一个问题...” + 那样的东西)。 + - 必须修正带来如下后果的问题:编译错误(对被标记为CONFIG_BROKEN的例外), + 内核崩溃,挂起,数据损坏,真正的安全问题,或者一些类似“哦,这不 + 好”的问题。简短的说,就是一些致命的问题。 + - 没有“理论上的竞争条件”,除非能给出竞争条件如何被利用的解释。 + - 不能存在任何的“琐碎的”修正(拼写修正,去掉多余空格之类的)。 + - 必须被相关子系统的维护者接受。 + - 必须遵循Documentation/translations/zh_CN/process/submitting-patches.rst里的规则。 + +向稳定版代码树提交补丁的过程: +------------------------------ + + - 在确认了补丁符合以上的规则后,将补丁发送到stable@vger.kernel.org。 + - 如果补丁被接受到队列里,发送者会收到一个ACK回复,如果没有被接受,收 + 到的是NAK回复。回复需要几天的时间,这取决于开发者的时间安排。 + - 被接受的补丁会被加到稳定版本队列里,等待其他开发者的审查。 + - 安全方面的补丁不要发到这个列表,应该发送到security@kernel.org。 + +审查周期: +---------- + + - 当稳定版的维护者决定开始一个审查周期,补丁将被发送到审查委员会,以 + 及被补丁影响的领域的维护者(除非提交者就是该领域的维护者)并且抄送 + 到linux-kernel邮件列表。 + - 审查委员会有48小时的时间,用来决定给该补丁回复ACK还是NAK。 + - 如果委员会中有成员拒绝这个补丁,或者linux-kernel列表上有人反对这个 + 补丁,并提出维护者和审查委员会之前没有意识到的问题,补丁会从队列中 + 丢弃。 + - 在审查周期结束的时候,那些得到ACK回应的补丁将会被加入到最新的稳定版 + 发布中,一个新的稳定版发布就此产生。 + - 安全性补丁将从内核安全小组那里直接接收到稳定版代码树中,而不是通过 + 通常的审查周期。请联系内核安全小组以获得关于这个过程的更多细节。 + +审查委员会: +------------ + - 由一些自愿承担这项任务的内核开发者,和几个非志愿的组成。 diff --git a/Documentation/translations/zh_CN/process/submit-checklist.rst b/Documentation/translations/zh_CN/process/submit-checklist.rst new file mode 100644 index 000000000000..89061aa8fdbe --- /dev/null +++ b/Documentation/translations/zh_CN/process/submit-checklist.rst @@ -0,0 +1,107 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/submit-checklist.rst <submitchecklist>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +.. _cn_submitchecklist: + +Linux内核补丁提交清单 +~~~~~~~~~~~~~~~~~~~~~ + +如果开发人员希望看到他们的内核补丁提交更快地被接受,那么他们应该做一些基本 +的事情。 + +这些都是在 +:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` +和其他有关提交Linux内核补丁的文档中提供的。 + +1) 如果使用工具,则包括定义/声明该工具的文件。不要依赖于其他头文件拉入您使用 + 的头文件。 + +2) 干净的编译: + + a) 使用适用或修改的 ``CONFIG`` 选项 ``=y``、``=m`` 和 ``=n`` 。没有GCC + 警告/错误,没有链接器警告/错误。 + + b) 通过allnoconfig、allmodconfig + + c) 使用 ``O=builddir`` 时可以成功编译 + +3) 通过使用本地交叉编译工具或其他一些构建场在多个CPU体系结构上构建。 + +4) PPC64是一种很好的交叉编译检查体系结构,因为它倾向于对64位的数使用无符号 + 长整型。 + +5) 如下所述 :ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>`. + 检查您的补丁是否为常规样式。在提交( ``scripts/check patch.pl`` )之前, + 使用补丁样式检查器检查是否有轻微的冲突。您应该能够处理您的补丁中存在的所有 + 违规行为。 + +6) 任何新的或修改过的 ``CONFIG`` 选项都不会弄脏配置菜单,并默认为关闭,除非 + 它们符合 ``Documentation/kbuild/kconfig-language.txt`` 中记录的异常条件, + 菜单属性:默认值. + +7) 所有新的 ``kconfig`` 选项都有帮助文本。 + +8) 已仔细审查了相关的 ``Kconfig`` 组合。这很难用测试来纠正——脑力在这里是有 + 回报的。 + +9) 用 sparse 检查干净。 + +10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 并修复他们发现的任何 + 问题。 + + .. note:: + + ``checkstack`` 并没有明确指出问题,但是任何一个在堆栈上使用超过512 + 字节的函数都可以进行更改。 + +11) 包括 :ref:`kernel-doc <kernel_doc>` 内核文档以记录全局内核API。(静态函数 + 不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 检查 + :ref:`kernel-doc <kernel_doc>` 并修复任何问题。 + +12) 通过以下选项同时启用的测试 ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``, + ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``, + ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``, + ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` + +13) 已经过构建和运行时测试,包括有或没有 ``CONFIG_SMP``, ``CONFIG_PREEMPT``. + +14) 如果补丁程序影响IO/磁盘等:使用或不使用 ``CONFIG_LBDAF`` 进行测试。 + +15) 所有代码路径都已在启用所有lockdep功能的情况下运行。 + +16) 所有新的/proc条目都记录在 ``Documentation/`` + +17) 所有新的内核引导参数都记录在 + Documentation/admin-guide/kernel-parameters.rst 中。 + +18) 所有新的模块参数都记录在 ``MODULE_PARM_DESC()`` + +19) 所有新的用户空间接口都记录在 ``Documentation/ABI/`` 中。有关详细信息, + 请参阅 ``Documentation/ABI/README`` 。更改用户空间接口的补丁应该抄送 + linux-api@vger.kernel.org。 + +20) 检查是否全部通过 ``make headers_check`` 。 + +21) 已通过至少注入slab和page分配失败进行检查。请参阅 ``Documentation/fault-injection/`` + 如果新代码是实质性的,那么添加子系统特定的故障注入可能是合适的。 + +22) 新添加的代码已经用 ``gcc -W`` 编译(使用 ``make EXTRA-CFLAGS=-W`` )。这 + 将产生大量噪声,但对于查找诸如“警告:有符号和无符号之间的比较”之类的错误 + 很有用。 + +23) 在它被合并到-mm补丁集中之后进行测试,以确保它仍然与所有其他排队的补丁以 + 及VM、VFS和其他子系统中的各种更改一起工作。 + +24) 所有内存屏障例如 ``barrier()``, ``rmb()``, ``wmb()`` 都需要源代码中的注 + 释来解释它们正在执行的操作及其原因的逻辑。 + +25) 如果补丁添加了任何ioctl,那么也要更新 ``Documentation/ioctl/ioctl-number.txt`` + +26) 如果修改后的源代码依赖或使用与以下 ``Kconfig`` 符号相关的任何内核API或 + 功能,则在禁用相关 ``Kconfig`` 符号和/或 ``=m`` (如果该选项可用)的情况 + 下测试以下多个构建[并非所有这些都同时存在,只是它们的各种/随机组合]: + + ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``, + ``CONFIG_NET``, ``CONFIG_INET=n`` (但是后者伴随 ``CONFIG_NET=y``). diff --git a/Documentation/translations/zh_CN/process/submitting-drivers.rst b/Documentation/translations/zh_CN/process/submitting-drivers.rst new file mode 100644 index 000000000000..72c6cd935821 --- /dev/null +++ b/Documentation/translations/zh_CN/process/submitting-drivers.rst @@ -0,0 +1,160 @@ +.. _cn_submittingdrivers: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/submitting-drivers.rst + <submittingdrivers>` + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者:: + + 中文版维护者: 李阳 Li Yang <leoyang.li@nxp.com> + 中文版翻译者: 李阳 Li Yang <leoyang.li@nxp.com> + 中文版校译者: 陈琦 Maggie Chen <chenqi@beyondsoft.com> + 王聪 Wang Cong <xiyou.wangcong@gmail.com> + 张巍 Zhang Wei <wezhang@outlook.com> + +如何向 Linux 内核提交驱动程序 +============================= + +这篇文档将会解释如何向不同的内核源码树提交设备驱动程序。请注意,如果你感 +兴趣的是显卡驱动程序,你也许应该访问 XFree86 项目(http://www.xfree86.org/) +和/或 X.org 项目 (http://x.org)。 + +另请参阅 Documentation/Documentation/translations/zh_CN/process/submitting-patches.rst 文档。 + + +分配设备号 +---------- + +块设备和字符设备的主设备号与从设备号是由 Linux 命名编号分配权威 LANANA( +现在是 Torben Mathiasen)负责分配。申请的网址是 http://www.lanana.org/。 +即使不准备提交到主流内核的设备驱动也需要在这里分配设备号。有关详细信息, +请参阅 Documentation/admin-guide/devices.rst。 + +如果你使用的不是已经分配的设备号,那么当你提交设备驱动的时候,它将会被强 +制分配一个新的设备号,即便这个设备号和你之前发给客户的截然不同。 + +设备驱动的提交对象 +------------------ + +Linux 2.0: + 此内核源码树不接受新的驱动程序。 + +Linux 2.2: + 此内核源码树不接受新的驱动程序。 + +Linux 2.4: + 如果所属的代码领域在内核的 MAINTAINERS 文件中列有一个总维护者, + 那么请将驱动程序提交给他。如果此维护者没有回应或者你找不到恰当的 + 维护者,那么请联系 Willy Tarreau <w@1wt.eu>。 + +Linux 2.6: + 除了遵循和 2.4 版内核同样的规则外,你还需要在 linux-kernel 邮件 + 列表上跟踪最新的 API 变化。向 Linux 2.6 内核提交驱动的顶级联系人 + 是 Andrew Morton <akpm@linux-foundation.org>。 + +决定设备驱动能否被接受的条件 +---------------------------- + +许可: 代码必须使用 GNU 通用公开许可证 (GPL) 提交给 Linux,但是 + 我们并不要求 GPL 是唯一的许可。你或许会希望同时使用多种 + 许可证发布,如果希望驱动程序可以被其他开源社区(比如BSD) + 使用。请参考 include/linux/module.h 文件中所列出的可被 + 接受共存的许可。 + +版权: 版权所有者必须同意使用 GPL 许可。最好提交者和版权所有者 + 是相同个人或实体。否则,必需列出授权使用 GPL 的版权所有 + 人或实体,以备验证之需。 + +接口: 如果你的驱动程序使用现成的接口并且和其他同类的驱动程序行 + 为相似,而不是去发明无谓的新接口,那么它将会更容易被接受。 + 如果你需要一个 Linux 和 NT 的通用驱动接口,那么请在用 + 户空间实现它。 + +代码: 请使用 Documentation/process/coding-style.rst 中所描述的 Linux 代码风 + 格。如果你的某些代码段(例如那些与 Windows 驱动程序包共 + 享的代码段)需要使用其他格式,而你却只希望维护一份代码, + 那么请将它们很好地区分出来,并且注明原因。 + +可移植性: 请注意,指针并不永远是 32 位的,不是所有的计算机都使用小 + 尾模式 (little endian) 存储数据,不是所有的人都拥有浮点 + 单元,不要随便在你的驱动程序里嵌入 x86 汇编指令。只能在 + x86 上运行的驱动程序一般是不受欢迎的。虽然你可能只有 x86 + 硬件,很难测试驱动程序在其他平台上是否可用,但是确保代码 + 可以被轻松地移植却是很简单的。 + +清晰度: 做到所有人都能修补这个驱动程序将会很有好处,因为这样你将 + 会直接收到修复的补丁而不是 bug 报告。如果你提交一个试图 + 隐藏硬件工作机理的驱动程序,那么它将会被扔进废纸篓。 + +电源管理: 因为 Linux 正在被很多移动设备和桌面系统使用,所以你的驱 + 动程序也很有可能被使用在这些设备上。它应该支持最基本的电 + 源管理,即在需要的情况下实现系统级休眠和唤醒要用到的 + .suspend 和 .resume 函数。你应该检查你的驱动程序是否能正 + 确地处理休眠与唤醒,如果实在无法确认,请至少把 .suspend + 函数定义成返回 -ENOSYS(功能未实现)错误。你还应该尝试确 + 保你的驱动在什么都不干的情况下将耗电降到最低。要获得驱动 + 程序测试的指导,请参阅 + Documentation/power/drivers-testing.txt。有关驱动程序电 + 源管理问题相对全面的概述,请参阅 + Documentation/driver-api/pm/devices.rst。 + +管理: 如果一个驱动程序的作者还在进行有效的维护,那么通常除了那 + 些明显正确且不需要任何检查的补丁以外,其他所有的补丁都会 + 被转发给作者。如果你希望成为驱动程序的联系人和更新者,最 + 好在代码注释中写明并且在 MAINTAINERS 文件中加入这个驱动 + 程序的条目。 + +不影响设备驱动能否被接受的条件 +------------------------------ + +供应商: 由硬件供应商来维护驱动程序通常是一件好事。不过,如果源码 + 树里已经有其他人提供了可稳定工作的驱动程序,那么请不要期 + 望“我是供应商”会成为内核改用你的驱动程序的理由。理想的情 + 况是:供应商与现有驱动程序的作者合作,构建一个统一完美的 + 驱动程序。 + +作者: 驱动程序是由大的 Linux 公司研发还是由你个人编写,并不影 + 响其是否能被内核接受。没有人对内核源码树享有特权。只要你 + 充分了解内核社区,你就会发现这一点。 + + +资源列表 +-------- + +Linux 内核主源码树: + ftp.??.kernel.org:/pub/linux/kernel/... + ?? == 你的国家代码,例如 "cn"、"us"、"uk"、"fr" 等等 + +Linux 内核邮件列表: + linux-kernel@vger.kernel.org + [可通过向majordomo@vger.kernel.org发邮件来订阅] + +Linux 设备驱动程序,第三版(探讨 2.6.10 版内核): + http://lwn.net/Kernel/LDD3/ (免费版) + +LWN.net: + 每周内核开发活动摘要 - http://lwn.net/ + + 2.6 版中 API 的变更: + + http://lwn.net/Articles/2.6-kernel-api/ + + 将旧版内核的驱动程序移植到 2.6 版: + + http://lwn.net/Articles/driver-porting/ + +内核新手(KernelNewbies): + 为新的内核开发者提供文档和帮助 + http://kernelnewbies.org/ + +Linux USB项目: + http://www.linux-usb.org/ + +写内核驱动的“不要”(Arjan van de Ven著): + http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf + +内核清洁工 (Kernel Janitor): + http://kernelnewbies.org/KernelJanitors diff --git a/Documentation/translations/zh_CN/process/submitting-patches.rst b/Documentation/translations/zh_CN/process/submitting-patches.rst new file mode 100644 index 000000000000..437c23b367bb --- /dev/null +++ b/Documentation/translations/zh_CN/process/submitting-patches.rst @@ -0,0 +1,682 @@ +.. _cn_submittingpatches: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` + +译者:: + + 中文版维护者: 钟宇 TripleX Chung <xxx.phy@gmail.com> + 中文版翻译者: 钟宇 TripleX Chung <xxx.phy@gmail.com> + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + 中文版校译者: 李阳 Li Yang <leoyang.li@nxp.com> + 王聪 Wang Cong <xiyou.wangcong@gmail.com> + + +如何让你的改动进入内核 +====================== + +对于想要将改动提交到 Linux 内核的个人或者公司来说,如果不熟悉“规矩”, +提交的流程会让人畏惧。本文档收集了一系列建议,这些建议可以大大的提高你 +的改动被接受的机会. + +以下文档含有大量简洁的建议, 具体请见: +:ref:`Documentation/process <development_process_main>` +同样,:ref:`Documentation/translations/zh_CN/process/submit-checklist.rst <cn_submitchecklist>` +给出在提交代码前需要检查的项目的列表。如果你在提交一个驱动程序,那么 +同时阅读一下: +:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>` + +其中许多步骤描述了Git版本控制系统的默认行为;如果您使用Git来准备补丁, +您将发现它为您完成的大部分机械工作,尽管您仍然需要准备和记录一组合理的 +补丁。一般来说,使用git将使您作为内核开发人员的生活更轻松。 + + +0) 获取当前源码树 +----------------- + +如果您没有一个可以使用当前内核源代码的存储库,请使用git获取一个。您将要 +从主线存储库开始,它可以通过以下方式获取:: + + git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + +但是,请注意,您可能不希望直接针对主线树进行开发。大多数子系统维护人员运 +行自己的树,并希望看到针对这些树准备的补丁。请参见MAINTAINERS文件中子系 +统的 **T:** 项以查找该树,或者简单地询问维护者该树是否未在其中列出。 + +仍然可以通过tarballs下载内核版本(如下一节所述),但这是进行内核开发的 +一种困难的方式。 + +1) "diff -up" +------------- + +使用 "diff -up" 或者 "diff -uprN" 来创建补丁。 + +所有内核的改动,都是以补丁的形式呈现的,补丁由 diff(1) 生成。创建补丁的 +时候,要确认它是以 "unified diff" 格式创建的,这种格式由 diff(1) 的 '-u' +参数生成。而且,请使用 '-p' 参数,那样会显示每个改动所在的C函数,使得 +产生的补丁容易读得多。补丁应该基于内核源代码树的根目录,而不是里边的任 +何子目录。 + +为一个单独的文件创建补丁,一般来说这样做就够了:: + + SRCTREE=linux + MYFILE=drivers/net/mydriver.c + + cd $SRCTREE + cp $MYFILE $MYFILE.orig + vi $MYFILE # make your change + cd .. + diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch + +为多个文件创建补丁,你可以解开一个没有修改过的内核源代码树,然后和你自 +己的代码树之间做 diff 。例如:: + + MYSRC=/devel/linux + + tar xvfz linux-3.19.tar.gz + mv linux-3.19 linux-3.19-vanilla + diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \ + linux-3.19-vanilla $MYSRC > /tmp/patch + +"dontdiff" 是内核在编译的时候产生的文件的列表,列表中的文件在 diff(1) +产生的补丁里会被跳过。 + +确定你的补丁里没有包含任何不属于这次补丁提交的额外文件。记得在用diff(1) +生成补丁之后,审阅一次补丁,以确保准确。 + +如果你的改动很散乱,你应该研究一下如何将补丁分割成独立的部分,将改动分 +割成一系列合乎逻辑的步骤。这样更容易让其他内核开发者审核,如果你想你的 +补丁被接受,这是很重要的。请参阅: +:ref:`cn_split_changes` + +如果你用 ``git`` , ``git rebase -i`` 可以帮助你这一点。如果你不用 ``git``, +``quilt`` <http://savannah.nongnu.org/projects/quilt> 另外一个流行的选择。 + +.. _cn_describe_changes: + +2) 描述你的改动 +--------------- + +描述你的问题。无论您的补丁是一行错误修复还是5000行新功能,都必须有一个潜在 +的问题激励您完成这项工作。让审稿人相信有一个问题值得解决,让他们读完第一段 +是有意义的。 + +描述用户可见的影响。直接崩溃和锁定是相当有说服力的,但并不是所有的错误都那么 +明目张胆。即使在代码审查期间发现了这个问题,也要描述一下您认为它可能对用户产 +生的影响。请记住,大多数Linux安装运行的内核来自二级稳定树或特定于供应商/产品 +的树,只从上游精选特定的补丁,因此请包含任何可以帮助您将更改定位到下游的内容: +触发的场景、DMESG的摘录、崩溃描述、性能回归、延迟尖峰、锁定等。 + +量化优化和权衡。如果您声称在性能、内存消耗、堆栈占用空间或二进制大小方面有所 +改进,请包括支持它们的数字。但也要描述不明显的成本。优化通常不是免费的,而是 +在CPU、内存和可读性之间进行权衡;或者,探索性的工作,在不同的工作负载之间进 +行权衡。请描述优化的预期缺点,以便审阅者可以权衡成本和收益。 + +一旦问题建立起来,就要详细地描述一下您实际在做什么。对于审阅者来说,用简单的 +英语描述代码的变化是很重要的,以验证代码的行为是否符合您的意愿。 + +如果您将补丁描述写在一个表单中,这个表单可以很容易地作为“提交日志”放入Linux +的源代码管理系统git中,那么维护人员将非常感谢您。见 :ref:`cn_explicit_in_reply_to`. + +每个补丁只解决一个问题。如果你的描述开始变长,这就表明你可能需要拆分你的补丁。 +请见 :ref:`cn_split_changes` + +提交或重新提交修补程序或修补程序系列时,请包括完整的修补程序说明和理由。不要 +只说这是补丁(系列)的第几版。不要期望子系统维护人员引用更早的补丁版本或引用 +URL来查找补丁描述并将其放入补丁中。也就是说,补丁(系列)及其描述应该是独立的。 +这对维护人员和审查人员都有好处。一些评审者可能甚至没有收到补丁的早期版本。 + +描述你在命令语气中的变化,例如“make xyzzy do frotz”而不是“[这个补丁]make +xyzzy do frotz”或“[我]changed xyzzy to do frotz”,就好像你在命令代码库改变 +它的行为一样。 + +如果修补程序修复了一个记录的bug条目,请按编号和URL引用该bug条目。如果补丁来 +自邮件列表讨论,请给出邮件列表存档的URL;使用带有 ``Message-ID`` 的 +https://lkml.kernel.org/ 重定向,以确保链接不会过时。 + +但是,在没有外部资源的情况下,尽量让你的解释可理解。除了提供邮件列表存档或 +bug的URL之外,还要总结需要提交补丁的相关讨论要点。 + +如果您想要引用一个特定的提交,不要只引用提交的 SHA-1 ID。还请包括提交的一行 +摘要,以便于审阅者了解它是关于什么的。例如:: + + Commit e21d2170f36602ae2708 ("video: remove unnecessary + platform_set_drvdata()") removed the unnecessary + platform_set_drvdata(), but left the variable "dev" unused, + delete it. + +您还应该确保至少使用前12位 SHA-1 ID. 内核存储库包含*许多*对象,使与较短的ID +发生冲突的可能性很大。记住,即使现在不会与您的六个字符ID发生冲突,这种情况 +可能五年后改变。 + +如果修补程序修复了特定提交中的错误,例如,使用 ``git bisct`` ,请使用带有前 +12个字符SHA-1 ID 的"Fixes:"标记和单行摘要。为了简化不要将标记拆分为多个, +行、标记不受分析脚本“75列换行”规则的限制。例如:: + + Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") + +下列 ``git config`` 设置可以添加让 ``git log``, ``git show`` 漂亮的显示格式:: + + [core] + abbrev = 12 + [pretty] + fixes = Fixes: %h (\"%s\") + +.. _cn_split_changes: + +3) 拆分你的改动 +--------------- + +将每个逻辑更改分隔成一个单独的补丁。 + +例如,如果你的改动里同时有bug修正和性能优化,那么把这些改动拆分到两个或 +者更多的补丁文件中。如果你的改动包含对API的修改,并且修改了驱动程序来适 +应这些新的API,那么把这些修改分成两个补丁。 + +另一方面,如果你将一个单独的改动做成多个补丁文件,那么将它们合并成一个 +单独的补丁文件。这样一个逻辑上单独的改动只被包含在一个补丁文件里。 + +如果有一个补丁依赖另外一个补丁来完成它的改动,那没问题。简单的在你的补 +丁描述里指出“这个补丁依赖某补丁”就好了。 + +在将您的更改划分为一系列补丁时,要特别注意确保内核在系列中的每个补丁之后 +都能正常构建和运行。使用 ``git bisect`` 来追踪问题的开发者可能会在任何时 +候分割你的补丁系列;如果你在中间引入错误,他们不会感谢你。 + +如果你不能将补丁浓缩成更少的文件,那么每次大约发送出15个,然后等待审查 +和集成。 + +4) 检查你的更改风格 +------------------- + +检查您的补丁是否存在基本样式冲突,详细信息可在 +:ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>` +中找到。如果不这样做,只会浪费审稿人的时间,并且会导致你的补丁被拒绝,甚至 +可能没有被阅读。 + +一个重要的例外是在将代码从一个文件移动到另一个文件时——在这种情况下,您不应 +该在移动代码的同一个补丁中修改移动的代码。这清楚地描述了移动代码和您的更改 +的行为。这大大有助于审查实际差异,并允许工具更好地跟踪代码本身的历史。 + +在提交之前,使用补丁样式检查程序检查补丁(scripts/check patch.pl)。不过, +请注意,样式检查程序应该被视为一个指南,而不是作为人类判断的替代品。如果您 +的代码看起来更好,但有违规行为,那么最好不要使用它。 + +检查者报告三个级别: + + - ERROR:很可能出错的事情 + - WARNING:需要仔细审查的事项 + - CHECK:需要思考的事情 + +您应该能够判断您的补丁中存在的所有违规行为。 + +5) 选择补丁收件人 +----------------- + +您应该总是在任何补丁上复制相应的子系统维护人员,以获得他们维护的代码;查看 +维护人员文件和源代码修订历史记录,以了解这些维护人员是谁。脚本 +scripts/get_Maintainer.pl在这个步骤中非常有用。如果您找不到正在工作的子系统 +的维护人员,那么Andrew Morton(akpm@linux-foundation.org)将充当最后的维护 +人员。 + +您通常还应该选择至少一个邮件列表来接收补丁集的。linux-kernel@vger.kernel.org +作为最后一个解决办法的列表,但是这个列表上的体积已经引起了许多开发人员的拒绝。 +在MAINTAINERS文件中查找子系统特定的列表;您的补丁可能会在那里得到更多的关注。 +不过,请不要发送垃圾邮件到无关的列表。 + +许多与内核相关的列表托管在vger.kernel.org上;您可以在 +http://vger.kernel.org/vger-lists.html 上找到它们的列表。不过,也有与内核相关 +的列表托管在其他地方。 + +不要一次发送超过15个补丁到vger邮件列表!!!! + +Linus Torvalds 是决定改动能否进入 Linux 内核的最终裁决者。他的 e-mail +地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多,所以一般 +的说,最好别给他发 e-mail。 + +如果您有修复可利用安全漏洞的补丁,请将该补丁发送到 security@kernel.org。对于 +严重的bug,可以考虑短期暂停以允许分销商向用户发布补丁;在这种情况下,显然不应 +将补丁发送到任何公共列表。 + +修复已发布内核中严重错误的补丁程序应该指向稳定版维护人员,方法是放这样的一行:: + + Cc: stable@vger.kernel.org + +进入补丁的签准区(注意,不是电子邮件收件人)。除了这个文件之外,您还应该阅读 +:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>` + +但是,请注意,一些子系统维护人员希望得出他们自己的结论,即哪些补丁应该被放到 +稳定的树上。尤其是网络维护人员,不希望看到单个开发人员在补丁中添加像上面这样 +的行。 + +如果更改影响到用户和内核接口,请向手册页维护人员(如维护人员文件中所列)发送 +手册页补丁,或至少发送更改通知,以便一些信息进入手册页。还应将用户空间API +更改复制到 linux-api@vger.kernel.org。 + +对于小的补丁,你也许会CC到搜集琐碎补丁的邮件列表(Trivial Patch Monkey) +trivial@kernel.org,那里专门收集琐碎的补丁。下面这样的补丁会被看作“琐碎的” +补丁: + + - 文档的拼写修正。 + - 修正会影响到 grep(1) 的拼写。 + - 警告信息修正(频繁的打印无用的警告是不好的。) + - 编译错误修正(代码逻辑的确是对的,只是编译有问题。) + - 运行时修正(只要真的修正了错误。) + - 移除使用了被废弃的函数/宏的代码(例如 check_region。) + - 联系方式和文档修正。 + - 用可移植的代码替换不可移植的代码(即使在体系结构相关的代码中,既然有 + - 人拷贝,只要它是琐碎的) + - 任何文件的作者/维护者对该文件的改动(例如 patch monkey 在重传模式下) + +(译注,关于“琐碎补丁”的一些说明:因为原文的这一部分写得比较简单,所以不得不 +违例写一下译注。"trivial"这个英文单词的本意是“琐碎的,不重要的。”但是在这里 +有稍微有一些变化,例如对一些明显的NULL指针的修正,属于运行时修正,会被归类 +到琐碎补丁里。虽然NULL指针的修正很重要,但是这样的修正往往很小而且很容易得到 +检验,所以也被归入琐碎补丁。琐碎补丁更精确的归类应该是 +“simple, localized & easy to verify”,也就是说简单的,局部的和易于检验的。 +trivial@kernel.org邮件列表的目的是针对这样的补丁,为提交者提供一个中心,来 +降低提交的门槛。) + +6) 没有 MIME 编码,没有链接,没有压缩,没有附件,只有纯文本 +----------------------------------------------------------- + +Linus 和其他的内核开发者需要阅读和评论你提交的改动。对于内核开发者来说 +,可以“引用”你的改动很重要,使用一般的 e-mail 工具,他们就可以在你的 +代码的任何位置添加评论。 + +因为这个原因,所有的提交的补丁都是 e-mail 中“内嵌”的。 + +.. warning:: + 如果你使用剪切-粘贴你的补丁,小心你的编辑器的自动换行功能破坏你的补丁 + +不要将补丁作为 MIME 编码的附件,不管是否压缩。很多流行的 e-mail 软件不 +是任何时候都将 MIME 编码的附件当作纯文本发送的,这会使得别人无法在你的 +代码中加评论。另外,MIME 编码的附件会让 Linus 多花一点时间来处理,这就 +降低了你的改动被接受的可能性。 + +例外:如果你的邮递员弄坏了补丁,那么有人可能会要求你使用mime重新发送补丁 + +请参阅 :ref:`Documentation/translations/zh_CN/process/email-clients.rst <cn_email_clients>` +以获取有关配置电子邮件客户端以使其不受影响地发送修补程序的提示。 + +7) e-mail 的大小 +---------------- + +大的改动对邮件列表不合适,对某些维护者也不合适。如果你的补丁,在不压缩 +的情况下,超过了300kB,那么你最好将补丁放在一个能通过 internet 访问的服 +务器上,然后用指向你的补丁的 URL 替代。但是请注意,如果您的补丁超过了 +300kb,那么它几乎肯定需要被破坏。 + +8)回复评审意见 +--------------- + +你的补丁几乎肯定会得到评审者对补丁改进方法的评论。您必须对这些评论作出 +回应;让补丁被忽略的一个好办法就是忽略审阅者的意见。不会导致代码更改的 +意见或问题几乎肯定会带来注释或变更日志的改变,以便下一个评审者更好地了解 +正在发生的事情。 + +一定要告诉审稿人你在做什么改变,并感谢他们的时间。代码审查是一个累人且 +耗时的过程,审查人员有时会变得暴躁。即使在这种情况下,也要礼貌地回应并 +解决他们指出的问题。 + +9)不要泄气或不耐烦 +------------------- + +提交更改后,请耐心等待。审阅者是忙碌的人,可能无法立即访问您的修补程序。 + +曾几何时,补丁曾在没有评论的情况下消失在空白中,但开发过程比现在更加顺利。 +您应该在一周左右的时间内收到评论;如果没有收到评论,请确保您已将补丁发送 +到正确的位置。在重新提交或联系审阅者之前至少等待一周-在诸如合并窗口之类的 +繁忙时间可能更长。 + +10)主题中包含 PATCH +-------------------- + +由于到linus和linux内核的电子邮件流量很高,通常会在主题行前面加上[PATCH] +前缀. 这使Linus和其他内核开发人员更容易将补丁与其他电子邮件讨论区分开。 + +11)签署你的作品-开发者原始认证 +------------------------------- + +为了加强对谁做了何事的追踪,尤其是对那些透过好几层的维护者的补丁,我们 +建议在发送出去的补丁上加一个 “sign-off” 的过程。 + +"sign-off" 是在补丁的注释的最后的简单的一行文字,认证你编写了它或者其他 +人有权力将它作为开放源代码的补丁传递。规则很简单:如果你能认证如下信息: + +开发者来源证书 1.1 +^^^^^^^^^^^^^^^^^^ + +对于本项目的贡献,我认证如下信息: + + (a)这些贡献是完全或者部分的由我创建,我有权利以文件中指出 + 的开放源代码许可证提交它;或者 + (b)这些贡献基于以前的工作,据我所知,这些以前的工作受恰当的开放 + 源代码许可证保护,而且,根据许可证,我有权提交修改后的贡献, + 无论是完全还是部分由我创造,这些贡献都使用同一个开放源代码许可证 + (除非我被允许用其它的许可证),正如文件中指出的;或者 + (c)这些贡献由认证(a),(b)或者(c)的人直接提供给我,而 + 且我没有修改它。 + (d)我理解并同意这个项目和贡献是公开的,贡献的记录(包括我 + 一起提交的个人记录,包括 sign-off )被永久维护并且可以和这个项目 + 或者开放源代码的许可证同步地再发行。 + +那么加入这样一行:: + + Signed-off-by: Random J Developer <random@developer.example.org> + +使用你的真名(抱歉,不能使用假名或者匿名。) + +有人在最后加上标签。现在这些东西会被忽略,但是你可以这样做,来标记公司 +内部的过程,或者只是指出关于 sign-off 的一些特殊细节。 + +如果您是子系统或分支维护人员,有时需要稍微修改收到的补丁,以便合并它们, +因为树和提交者中的代码不完全相同。如果你严格遵守规则(c),你应该要求提交者 +重新发布,但这完全是在浪费时间和精力。规则(b)允许您调整代码,但是更改一个 +提交者的代码并让他认可您的错误是非常不礼貌的。要解决此问题,建议在最后一个 +由签名行和您的行之间添加一行,指示更改的性质。虽然这并不是强制性的,但似乎 +在描述前加上您的邮件和/或姓名(全部用方括号括起来),这足以让人注意到您对最 +后一分钟的更改负有责任。例如:: + + Signed-off-by: Random J Developer <random@developer.example.org> + [lucky@maintainer.example.org: struct foo moved from foo.c to foo.h] + Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org> + +如果您维护一个稳定的分支机构,同时希望对作者进行致谢、跟踪更改、合并修复并 +保护提交者不受投诉,那么这种做法尤其有用。请注意,在任何情况下都不能更改作者 +的ID(From 头),因为它是出现在更改日志中的标识。 + +对回合(back-porters)的特别说明:在提交消息的顶部(主题行之后)插入一个补丁 +的起源指示似乎是一种常见且有用的实践,以便于跟踪。例如,下面是我们在3.x稳定 +版本中看到的内容:: + + Date: Tue Oct 7 07:26:38 2014 -0400 + + libata: Un-break ATA blacklist + + commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream. + +还有, 这里是一个旧版内核中的一个回合补丁:: + + Date: Tue May 13 22:12:27 2008 +0200 + + wireless, airo: waitbusy() won't delay + + [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a] + +12)何时使用Acked-by:,CC:,和Co-Developed by: +---------------------------------------------- + +Singed-off-by: 标记表示签名者参与了补丁的开发,或者他/她在补丁的传递路径中。 + +如果一个人没有直接参与补丁的准备或处理,但希望表示并记录他们对补丁的批准, +那么他们可以要求在补丁的变更日志中添加一个 Acked-by: + +Acked-by:通常由受影响代码的维护者使用,当该维护者既没有贡献也没有转发补丁时。 + +Acked-by: 不像签字人那样正式。这是一个记录,确认人至少审查了补丁,并表示接受。 +因此,补丁合并有时会手动将Acker的“Yep,looks good to me”转换为 Acked-By:(但 +请注意,通常最好要求一个明确的Ack)。 + +Acked-by:不一定表示对整个补丁的确认。例如,如果一个补丁影响多个子系统,并且 +有一个:来自一个子系统维护者,那么这通常表示只确认影响维护者代码的部分。这里 +应该仔细判断。如有疑问,应参考邮件列表档案中的原始讨论。 + +如果某人有机会对补丁进行评论,但没有提供此类评论,您可以选择在补丁中添加 ``Cc:`` +这是唯一一个标签,它可以在没有被它命名的人显式操作的情况下添加,但它应该表明 +这个人是在补丁上抄送的。讨论中包含了潜在利益相关方。 + +Co-developed-by: 声明补丁是由多个开发人员共同创建的;当几个人在一个补丁上工 +作时,它用于将属性赋予共同作者(除了 From: 所赋予的作者之外)。因为 +Co-developed-by: 表示作者身份,所以每个共同开发人:必须紧跟在相关合作作者的 +签名之后。标准的签核程序要求:标记的签核顺序应尽可能反映补丁的时间历史,而不 +管作者是通过 From :还是由 Co-developed-by: 共同开发的。值得注意的是,最后一 +个签字人:必须始终是提交补丁的开发人员。 + +注意,当作者也是电子邮件标题“发件人:”行中列出的人时,“From: ” 标记是可选的。 + +作者提交的补丁程序示例:: + + <changelog> + + Co-developed-by: First Co-Author <first@coauthor.example.org> + Signed-off-by: First Co-Author <first@coauthor.example.org> + Co-developed-by: Second Co-Author <second@coauthor.example.org> + Signed-off-by: Second Co-Author <second@coauthor.example.org> + Signed-off-by: From Author <from@author.example.org> + +合作开发者提交的补丁示例:: + + From: From Author <from@author.example.org> + + <changelog> + + Co-developed-by: Random Co-Author <random@coauthor.example.org> + Signed-off-by: Random Co-Author <random@coauthor.example.org> + Signed-off-by: From Author <from@author.example.org> + Co-developed-by: Submitting Co-Author <sub@coauthor.example.org> + Signed-off-by: Submitting Co-Author <sub@coauthor.example.org> + + +13)使用报告人:、测试人:、审核人:、建议人:、修复人: +-------------------------------------------------------- + +Reported-by: 给那些发现错误并报告错误的人致谢,它希望激励他们在将来再次帮助 +我们。请注意,如果bug是以私有方式报告的,那么在使用Reported-by标记之前,请 +先请求权限。 + +Tested-by: 标记表示补丁已由指定的人(在某些环境中)成功测试。这个标签通知 +维护人员已经执行了一些测试,为将来的补丁提供了一种定位测试人员的方法,并确 +保测试人员的信誉。 + +Reviewed-by:相反,根据审查人的声明,表明该补丁已被审查并被认为是可接受的: + + +审查人的监督声明 +^^^^^^^^^^^^^^^^ + +通过提供我的 Reviewed-by,我声明: + + (a) 我已经对这个补丁进行了一次技术审查,以评估它是否适合被包含到 + 主线内核中。 + + (b) 与补丁相关的任何问题、顾虑或问题都已反馈给提交者。我对提交者对 + 我的评论的回应感到满意。 + + (c) 虽然这一提交可能会改进一些东西,但我相信,此时,(1)对内核 + 进行了有价值的修改,(2)没有包含争论中涉及的已知问题。 + + (d) 虽然我已经审查了补丁并认为它是健全的,但我不会(除非另有明确 + 说明)作出任何保证或保证它将在任何给定情况下实现其规定的目的 + 或正常运行。 + +Reviewed-by 是一种观点声明,即补丁是对内核的适当修改,没有任何遗留的严重技术 +问题。任何感兴趣的审阅者(完成工作的人)都可以为一个补丁提供一个 Review-by +标签。此标签用于向审阅者提供致谢,并通知维护者已在修补程序上完成的审阅程度。 +Reviewed-by: 当由已知了解主题区域并执行彻底检查的审阅者提供时,通常会增加 +补丁进入内核的可能性。 + +Suggested-by: 表示补丁的想法是由指定的人提出的,并确保将此想法归功于指定的 +人。请注意,未经许可,不得添加此标签,特别是如果该想法未在公共论坛上发布。 +这就是说,如果我们勤快地致谢我们的创意者,他们很有希望在未来得到鼓舞,再次 +帮助我们。 + +Fixes: 指示补丁在以前的提交中修复了一个问题。它可以很容易地确定错误的来源, +这有助于检查错误修复。这个标记还帮助稳定内核团队确定应该接收修复的稳定内核 +版本。这是指示补丁修复的错误的首选方法。请参阅 :ref:`cn_describe_changes` +描述您的更改以了解更多详细信息。 + +.. _cn_the_canonical_patch_format: + +12)标准补丁格式 +---------------- + +本节描述如何格式化补丁本身。请注意,如果您的补丁存储在 ``Git`` 存储库中,则 +可以使用 ``git format-patch`` 进行正确的补丁格式设置。但是,这些工具无法创建 +必要的文本,因此请务必阅读下面的说明。 + +标准的补丁,标题行是:: + + Subject: [PATCH 001/123] 子系统:一句话概述 + +标准补丁的信体存在如下部分: + + - 一个 "from" 行指出补丁作者。后跟空行(仅当发送修补程序的人不是作者时才需要)。 + + - 解释的正文,行以75列包装,这将被复制到永久变更日志来描述这个补丁。 + + - 一个空行 + + - 上面描述的“Signed-off-by” 行,也将出现在更改日志中。 + + - 只包含 ``---`` 的标记线。 + + - 任何其他不适合放在变更日志的注释。 + + - 实际补丁( ``diff`` 输出)。 + +标题行的格式,使得对标题行按字母序排序非常的容易 - 很多 e-mail 客户端都 +可以支持 - 因为序列号是用零填充的,所以按数字排序和按字母排序是一样的。 + +e-mail 标题中的“子系统”标识哪个内核子系统将被打补丁。 + +e-mail 标题中的“一句话概述”扼要的描述 e-mail 中的补丁。“一句话概述” +不应该是一个文件名。对于一个补丁系列(“补丁系列”指一系列的多个相关补 +丁),不要对每个补丁都使用同样的“一句话概述”。 + +记住 e-mail 的“一句话概述”会成为该补丁的全局唯一标识。它会蔓延到 git +的改动记录里。然后“一句话概述”会被用在开发者的讨论里,用来指代这个补 +丁。用户将希望通过 google 来搜索"一句话概述"来找到那些讨论这个补丁的文 +章。当人们在两三个月后使用诸如 ``gitk`` 或 ``git log --oneline`` 之类 +的工具查看数千个补丁时,也会很快看到它。 + +出于这些原因,概述必须不超过70-75个字符,并且必须描述补丁的更改以及为 +什么需要补丁。既要简洁又要描述性很有挑战性,但写得好的概述应该这样做。 + +概述的前缀可以用方括号括起来:“Subject: [PATCH <tag>...] <概述>”。标记 +不被视为概述的一部分,而是描述应该如何处理补丁。如果补丁的多个版本已发 +送出来以响应评审(即“v1,v2,v3”)或“rfc”,以指示评审请求,那么通用标记 +可能包括版本描述符。如果一个补丁系列中有四个补丁,那么各个补丁可以这样 +编号:1/4、2/4、3/4、4/4。这可以确保开发人员了解补丁应用的顺序,并且他们 +已经查看或应用了补丁系列中的所有补丁。 + +一些标题的例子:: + + Subject: [patch 2/5] ext2: improve scalability of bitmap searching + Subject: [PATCHv2 001/207] x86: fix eflags tracking + +"From" 行是信体里的最上面一行,具有如下格式: + From: Patch Author <author@example.com> + +"From" 行指明在永久改动日志里,谁会被确认为作者。如果没有 "From" 行,那 +么邮件头里的 "From: " 行会被用来决定改动日志中的作者。 + +说明的主题将会被提交到永久的源代码改动日志里,因此对那些早已经不记得和 +这个补丁相关的讨论细节的有能力的读者来说,是有意义的。包括补丁程序定位 +错误的(内核日志消息、OOPS消息等)症状,对于搜索提交日志以寻找适用补丁的人 +尤其有用。如果一个补丁修复了一个编译失败,那么可能不需要包含所有编译失败; +只要足够让搜索补丁的人能够找到它就行了。与概述一样,既要简洁又要描述性。 + +"---" 标记行对于补丁处理工具要找到哪里是改动日志信息的结束,是不可缺少 +的。 + +对于 "---" 标记之后的额外注解,一个好的用途就是用来写 diffstat,用来显 +示修改了什么文件和每个文件都增加和删除了多少行。diffstat 对于比较大的补 +丁特别有用。其余那些只是和时刻或者开发者相关的注解,不合适放到永久的改 +动日志里的,也应该放这里。 +使用 diffstat的选项 "-p 1 -w 70" 这样文件名就会从内核源代码树的目录开始 +,不会占用太宽的空间(很容易适合80列的宽度,也许会有一些缩进。) + +在后面的参考资料中能看到适当的补丁格式的更多细节。 + +.. _cn_explicit_in_reply_to: + +15) 明确回复邮件头(In-Reply-To) +------------------------------- + +手动添加回复补丁的的标题头(In-Reply_To:) 是有帮助的(例如,使用 ``git send-email`` ) +将补丁与以前的相关讨论关联起来,例如,将bug修复程序链接到电子邮件和bug报告。 +但是,对于多补丁系列,最好避免在回复时使用链接到该系列的旧版本。这样, +补丁的多个版本就不会成为电子邮件客户端中无法管理的引用序列。如果链接有用, +可以使用 https://lkml.kernel.org/ 重定向器(例如,在封面电子邮件文本中) +链接到补丁系列的早期版本。 + +16) 发送git pull请求 +-------------------- + +如果您有一系列补丁,那么让维护人员通过git pull操作将它们直接拉入子系统存储 +库可能是最方便的。但是,请注意,从开发人员那里获取补丁比从邮件列表中获取补 +丁需要更高的信任度。因此,许多子系统维护人员不愿意接受请求,特别是来自新的 +未知开发人员的请求。如果有疑问,您可以在封面邮件中使用pull 请求作为补丁系列 +正常发布的一个选项,让维护人员可以选择使用其中之一。 + +pull 请求的主题行中应该有[Git Pull]。请求本身应该在一行中包含存储库名称和 +感兴趣的分支;它应该看起来像:: + + Please pull from + + git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus + + to get these changes: + + +pull 请求还应该包含一条整体消息,说明请求中将包含什么,一个补丁本身的 ``Git shortlog`` +以及一个显示补丁系列整体效果的 ``diffstat`` 。当然,将所有这些信息收集在一起 +的最简单方法是让 ``git`` 使用 ``git request-pull`` 命令为您完成这些工作。 + +一些维护人员(包括Linus)希望看到来自已签名提交的请求;这增加了他们对你的 +请求信心。特别是,在没有签名标签的情况下,Linus 不会从像 Github 这样的公共 +托管站点拉请求。 + +创建此类签名的第一步是生成一个 GNRPG 密钥,并由一个或多个核心内核开发人员对 +其进行签名。这一步对新开发人员来说可能很困难,但没有办法绕过它。参加会议是 +找到可以签署您的密钥的开发人员的好方法。 + +一旦您在Git 中准备了一个您希望有人拉的补丁系列,就用 ``git tag -s`` 创建一 +个签名标记。这将创建一个新标记,标识该系列中的最后一次提交,并包含用您的私 +钥创建的签名。您还可以将changelog样式的消息添加到标记中;这是一个描述拉请求 +整体效果的理想位置。 + +如果维护人员将要从中提取的树不是您正在使用的存储库,请不要忘记将已签名的标记 +显式推送到公共树。 + +生成拉请求时,请使用已签名的标记作为目标。这样的命令可以实现:: + + git request-pull master git://my.public.tree/linux.git my-signed-tag + +参考文献 +-------- + +Andrew Morton, "The perfect patch" (tpp). + <http://www.ozlabs.org/~akpm/stuff/tpp.txt> + +Jeff Garzik, "Linux kernel patch submission format". + <http://linux.yyz.us/patch-format.html> + +Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer". + <http://www.kroah.com/log/linux/maintainer.html> + + <http://www.kroah.com/log/linux/maintainer-02.html> + + <http://www.kroah.com/log/linux/maintainer-03.html> + + <http://www.kroah.com/log/linux/maintainer-04.html> + + <http://www.kroah.com/log/linux/maintainer-05.html> + + <http://www.kroah.com/log/linux/maintainer-06.html> + +NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people! + <https://lkml.org/lkml/2005/7/11/336> + +Kernel Documentation/process/coding-style.rst: + :ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>` + +Linus Torvalds's mail on the canonical patch format: + <http://lkml.org/lkml/2005/4/7/183> + +Andi Kleen, "On submitting kernel patches" + Some strategies to get difficult or controversial changes in. + + http://halobates.de/on-submitting-patches.pdf diff --git a/Documentation/translations/zh_CN/process/volatile-considered-harmful.rst b/Documentation/translations/zh_CN/process/volatile-considered-harmful.rst new file mode 100644 index 000000000000..48b32ce58ef1 --- /dev/null +++ b/Documentation/translations/zh_CN/process/volatile-considered-harmful.rst @@ -0,0 +1,106 @@ +.. _cn_volatile_considered_harmful: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/volatile-considered-harmful.rst + <volatile_considered_harmful>` + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者:: + + 英文版维护者: Jonathan Corbet <corbet@lwn.net> + 中文版维护者: 伍鹏 Bryan Wu <bryan.wu@analog.com> + 中文版翻译者: 伍鹏 Bryan Wu <bryan.wu@analog.com> + 中文版校译者: 张汉辉 Eugene Teo <eugeneteo@kernel.sg> + 杨瑞 Dave Young <hidave.darkstar@gmail.com> + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +为什么不应该使用“volatile”类型 +============================== + +C程序员通常认为volatile表示某个变量可以在当前执行的线程之外被改变;因此,在内核 +中用到共享数据结构时,常常会有C程序员喜欢使用volatile这类变量。换句话说,他们经 +常会把volatile类型看成某种简易的原子变量,当然它们不是。在内核中使用volatile几 +乎总是错误的;本文档将解释为什么这样。 + +理解volatile的关键是知道它的目的是用来消除优化,实际上很少有人真正需要这样的应 +用。在内核中,程序员必须防止意外的并发访问破坏共享的数据结构,这其实是一个完全 +不同的任务。用来防止意外并发访问的保护措施,可以更加高效的避免大多数优化相关的 +问题。 + +像volatile一样,内核提供了很多原语来保证并发访问时的数据安全(自旋锁, 互斥量,内 +存屏障等等),同样可以防止意外的优化。如果可以正确使用这些内核原语,那么就没有 +必要再使用volatile。如果仍然必须使用volatile,那么几乎可以肯定在代码的某处有一 +个bug。在正确设计的内核代码中,volatile能带来的仅仅是使事情变慢。 + +思考一下这段典型的内核代码:: + + spin_lock(&the_lock); + do_something_on(&shared_data); + do_something_else_with(&shared_data); + spin_unlock(&the_lock); + +如果所有的代码都遵循加锁规则,当持有the_lock的时候,不可能意外的改变shared_data的 +值。任何可能访问该数据的其他代码都会在这个锁上等待。自旋锁原语跟内存屏障一样—— 它 +们显式的用来书写成这样 —— 意味着数据访问不会跨越它们而被优化。所以本来编译器认为 +它知道在shared_data里面将有什么,但是因为spin_lock()调用跟内存屏障一样,会强制编 +译器忘记它所知道的一切。那么在访问这些数据时不会有优化的问题。 + +如果shared_data被声名为volatile,锁操作将仍然是必须的。就算我们知道没有其他人正在 +使用它,编译器也将被阻止优化对临界区内shared_data的访问。在锁有效的同时, +shared_data不是volatile的。在处理共享数据的时候,适当的锁操作可以不再需要 +volatile —— 并且是有潜在危害的。 + +volatile的存储类型最初是为那些内存映射的I/O寄存器而定义。在内核里,寄存器访问也应 +该被锁保护,但是人们也不希望编译器“优化”临界区内的寄存器访问。内核里I/O的内存访问 +是通过访问函数完成的;不赞成通过指针对I/O内存的直接访问,并且不是在所有体系架构上 +都能工作。那些访问函数正是为了防止意外优化而写的,因此,再说一次,volatile类型不 +是必需的。 + +另一种引起用户可能使用volatile的情况是当处理器正忙着等待一个变量的值。正确执行一 +个忙等待的方法是:: + + while (my_variable != what_i_want) + cpu_relax(); + +cpu_relax()调用会降低CPU的能量消耗或者让位于超线程双处理器;它也作为内存屏障一样出 +现,所以,再一次,volatile不是必需的。当然,忙等待一开始就是一种反常规的做法。 + +在内核中,一些稀少的情况下volatile仍然是有意义的: + + - 在一些体系架构的系统上,允许直接的I/0内存访问,那么前面提到的访问函数可以使用 + volatile。基本上,每一个访问函数调用它自己都是一个小的临界区域并且保证了按照 + 程序员期望的那样发生访问操作。 + + - 某些会改变内存的内联汇编代码虽然没有什么其他明显的附作用,但是有被GCC删除的可 + 能性。在汇编声明中加上volatile关键字可以防止这种删除操作。 + + - Jiffies变量是一种特殊情况,虽然每次引用它的时候都可以有不同的值,但读jiffies + 变量时不需要任何特殊的加锁保护。所以jiffies变量可以使用volatile,但是不赞成 + 其他跟jiffies相同类型变量使用volatile。Jiffies被认为是一种“愚蠢的遗留物" + (Linus的话)因为解决这个问题比保持现状要麻烦的多。 + + - 由于某些I/0设备可能会修改连续一致的内存,所以有时,指向连续一致内存的数据结构 + 的指针需要正确的使用volatile。网络适配器使用的环状缓存区正是这类情形的一个例 + 子,其中适配器用改变指针来表示哪些描述符已经处理过了。 + +对于大多代码,上述几种可以使用volatile的情况都不适用。所以,使用volatile是一种 +bug并且需要对这样的代码额外仔细检查。那些试图使用volatile的开发人员需要退一步想想 +他们真正想实现的是什么。 + +非常欢迎删除volatile变量的补丁 - 只要证明这些补丁完整的考虑了并发问题。 + +注释 +---- + +[1] http://lwn.net/Articles/233481/ +[2] http://lwn.net/Articles/233482/ + +致谢 +---- + +最初由Randy Dunlap推动并作初步研究 +由Jonathan Corbet撰写 +参考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila, +H. Peter Anvin,Philipp Hahn和Stefan Richter的意见改善了本档。 |