diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
commit | ace9429bb58fd418f0c81d4c2835699bddf6bde6 (patch) | |
tree | b2d64bc10158fdd5497876388cd68142ca374ed3 /Documentation/translations/zh_CN/process | |
parent | Initial commit. (diff) | |
download | linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.tar.xz linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.zip |
Adding upstream version 6.6.15.upstream/6.6.15
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
27 files changed, 6187 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 0000000000..4f9284cbe3 --- /dev/null +++ b/Documentation/translations/zh_CN/process/1.Intro.rst @@ -0,0 +1,195 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/1.Intro.rst <development_process_intro>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_process_intro: + +引言 +==== + +内容提要 +-------- + +本节的其余部分涵盖了内核开发的过程,以及开发人员及其雇主在这方面可能遇到的 +各种问题。有很多原因使内核代码应被合并到正式的(“主线”)内核中,包括对用户 +的自动可用性、多种形式的社区支持以及影响内核开发方向的能力。提供给Linux内核 +的代码必须在与GPL兼容的许可证下可用。 + +:ref:`cn_development_process` 介绍了开发过程、内核发布周期和合并窗口的机制。 +涵盖了补丁开发、审查和合并周期中的各个阶段。还有一些关于工具和邮件列表的讨论? +鼓励希望开始内核开发的开发人员跟踪并修复缺陷以作为初步练习。 + + +: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年开始,这个内核已经发展成为一个最好的操作系统组件, +运行在袖珍数字音乐播放器、台式电脑、现存最大的超级计算机以及所有类型的系统上。 +它是一种适用于几乎任何情况的健壮、高效和可扩展的解决方案。 + +随着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 0000000000..e68c9de0f7 --- /dev/null +++ b/Documentation/translations/zh_CN/process/2.Process.rst @@ -0,0 +1,365 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/2.Process.rst <development_process>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_process: + +开发流程如何进行 +================ + +90年代早期的Linux内核开发是一件相当松散的事情,涉及的用户和开发人员相对较少。 +由于拥有数以百万计的用户群,且每年有大约2000名开发人员参与进来,内核因此必须 +发展出许多既定流程来保证开发的顺利进行。要参与到流程中来,需要对此流程的进行 +方式有一个扎实的理解。 + +总览 +---- + +内核开发人员使用一个松散的基于时间的发布过程,每两到三个月发布一次新的主要 +内核版本。最近的发布历史记录如下: + + ====== ================= + 5.0 2019年3月3日 + 5.1 2019年5月5日 + 5.2 2019年7月7日 + 5.3 2019年9月15日 + 5.4 2019年11月24日 + 5.5 2020年1月6日 + ====== ================= + +每个5.x版本都是一个主要的内核版本,具有新特性、内部API更改等等。一个典型的5.x +版本包含大约13000个变更集,变更了几十万行代码。因此,5.x是Linux内核开发的前 +沿;内核使用滚动开发模型,不断集成重大变化。 + +对于每个版本的补丁合并,遵循一个相对简单的规则。在每个开发周期的开头,“合并 +窗口”被打开。这时,被认为足够稳定(并且被开发社区接受)的代码被合并到主线内 +核中。在这段时间内,新开发周期的大部分变更(以及所有主要变更)将以接近每天 +1000次变更(“补丁”或“变更集”)的速度合并。 + +(顺便说一句,值得注意的是,合并窗口期间集成的更改并不是凭空产生的;它们是经 +提前收集、测试和分级的。稍后将详细描述该过程的工作方式。) + +合并窗口持续大约两周。在这段时间结束时,Linus Torvalds将声明窗口已关闭,并 +释放第一个“rc”内核。例如,对于目标为5.6的内核,在合并窗口结束时发生的释放 +将被称为5.6-rc1。-rc1 版本是一个信号,表示合并新特性的时间已经过去,稳定下一 +个内核的时间已经到来。 + +在接下来的6到10周内,只有修复问题的补丁才应该提交给主线。有时会允许更大的 +更改,但这种情况很少发生;试图在合并窗口外合并新功能的开发人员往往受不到 +友好的接待。一般来说,如果您错过了给定特性的合并窗口,最好的做法是等待下一 +个开发周期。(偶尔会对未支持硬件的驱动程序进行例外;如果它们不改变已有代码, +则不会导致回归,应该可以随时被安全地加入)。 + +随着修复程序进入主线,补丁速度将随着时间的推移而变慢。Linus大约每周发布一次 +新的-rc内核;在内核被认为足够稳定并最终发布前,一般会达到-rc6到-rc9之间。 +然后,整个过程又重新开始了。 + +例如,这里是5.4的开发周期进行情况(2019年): + + ============== ============================== + 九月 15 5.3 稳定版发布 + 九月 30 5.4-rc1 合并窗口关闭 + 十月 6 5.4-rc2 + 十月 13 5.4-rc3 + 十月 20 5.4-rc4 + 十月 27 5.4-rc5 + 十一月 3 5.4-rc6 + 十一月 10 5.4-rc7 + 十一月 17 5.4-rc8 + 十一月 24 5.4 稳定版发布 + ============== ============================== + +开发人员如何决定何时结束开发周期并创建稳定版本?最重要的指标是以前版本的 +回归列表。不欢迎出现任何错误,但是那些破坏了以前能工作的系统的错误被认为是 +特别严重的。因此,导致回归的补丁是不受欢迎的,很可能在稳定期内删除。 + +开发人员的目标是在稳定发布之前修复所有已知的回归。在现实世界中,这种完美是 +很难实现的;在这种规模的项目中,变数太多了。需要说明的是,延迟最终版本只会 +使问题变得更糟;等待下一个合并窗口的更改将变多,导致下次出现更多的回归错误。 +因此,大多数5.x内核都有一些已知的回归错误,不过,希望没有一个是严重的。 + +一旦一个稳定的版本发布,它的持续维护工作就被移交给“稳定团队”,目前由 +Greg Kroah-Hartman领导。稳定团队将使用5.x.y编号方案不定期地发布稳定版本的 +更新。要合入更新版本,补丁必须(1)修复一个重要的缺陷,且(2)已经合并到 +下一个开发版本主线中。内核通常会在其初始版本后的一个以上的开发周期内收到 +稳定版更新。例如,5.2内核的历史如下(2019年): + + ============== =============================== + 七月 7 5.2 稳定版发布 + 七月 13 5.2.1 + 七月 21 5.2.2 + 七月 26 5.2.3 + 七月 28 5.2.4 + 七月 31 5.2.5 + ... ... + 十月 11 5.2.21 + ============== =============================== + +5.2.21是5.2版本的最终稳定更新。 + +有些内核被指定为“长期”内核;它们将得到更长时间的支持。在本文中,当前的长期 +内核及其维护者是: + + ====== ================================ ================ + 3.16 Ben Hutchings (长期稳定内核) + 4.4 Greg Kroah-Hartman & Sasha Levin (长期稳定内核) + 4.9 Greg Kroah-Hartman & Sasha Levin + 4.14 Greg Kroah-Hartman & Sasha Levin + 4.19 Greg Kroah-Hartman & Sasha Levin + 5.4 Greg Kroah-Hartman & Sasha Levin + ====== ================================ ================ + +长期支持内核的选择纯粹是维护人员是否有需求和时间来维护该版本的问题。 +目前还没有为即将发布的任何特定版本提供长期支持的已知计划。 + +补丁的生命周期 +-------------- + +补丁不会直接从开发人员的键盘进入主线内核。相反,有一个稍微复杂(如果有些非 +正式)的过程,旨在确保对每个补丁进行质量审查,并确保每个补丁实现了一个在主线 +中需要的更改。对于小的修复,这个过程可能会很快完成,,而对于较大或有争议的 +变更,可能会持续数年。许多开发人员的沮丧来自于对这个过程缺乏理解或者试图绕过它。 + +为了减少这种挫败,本文将描述补丁如何进入内核。下面的介绍以一种较为理想化的 +方式描述了这个过程。更详细的过程将在后面的章节中介绍。 + +补丁通常要经历以下阶段: + +- 设计。这就是补丁的真正需求——以及满足这些需求的方式——所在。设计工作通常 + 是在不涉及社区的情况下完成的,但是如果可能的话,最好是在公开的情况下完成 + 这项工作;这样可以节省很多稍后再重新设计的时间。 + +- 早期评审。补丁被发布到相关的邮件列表中,列表中的开发人员会回复他们可能有 + 的任何评论。如果一切顺利的话,这个过程应该会发现补丁的任何主要问题。 + +- 更广泛的评审。当补丁接近准备好纳入主线时,它应该被相关的子系统维护人员 + 接受——尽管这种接受并不能保证补丁会一直延伸到主线。补丁将出现在维护人员的 + 子系统树中,并进入 -next 树(如下所述)。当流程进行时,此步骤将会对补丁 + 进行更广泛的审查,并发现由于将此补丁与其他人所做的工作合并而导致的任何 + 问题。 + +- 请注意,大多数维护人员也有日常工作,因此合并补丁可能不是他们的最优先工作。 + 如果您的补丁得到了需要更改的反馈,那么您应该进行这些更改,或者解释为何 + 不应该进行这些更改。如果您的补丁没有评审意见,也没有被其相应的子系统或 + 驱动程序维护者接受,那么您应该坚持不懈地将补丁更新到当前内核使其可被正常 + 应用,并不断地发送它以供审查和合并。 + +- 合并到主线。最终,一个成功的补丁将被合并到由LinusTorvalds管理的主线存储库 + 中。此时可能会出现更多的评论和/或问题;对开发人员来说应对这些问题并解决 + 出现的任何问题仍很重要。 + +- 稳定版发布。大量用户可能受此补丁影响,因此可能再次出现新的问题。 + +- 长期维护。虽然开发人员在合并代码后可能会忘记代码,但这种行为往往会给开发 + 社区留下不良印象。合并代码消除了一些维护负担,因为其他人将修复由API更改 + 引起的问题。但是,如果代码要长期保持可用,原始开发人员应该继续为代码负责。 + +内核开发人员(或他们的雇主)犯的最大错误之一是试图将流程简化为一个“合并到 +主线”步骤。这种方法总是会让所有相关人员感到沮丧。 + +补丁如何进入内核 +---------------- + +只有一个人可以将补丁合并到主线内核存储库中:Linus Torvalds。但是,在进入 +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)目录中找到: + + https://www.ozlabs.org/~akpm/mmotm/ + +然而,使用MMOTM树可能会十分令人头疼;它甚至可能无法编译。 + +下一个周期补丁合并的主要树是linux-next,由Stephen Rothwell 维护。根据设计 +linux-next 是下一个合并窗口关闭后主线的快照。linux-next树在Linux-kernel 和 +Linux-next 邮件列表中发布,可从以下位置下载: + + https://www.kernel.org/pub/linux/kernel/next/ + +Linux-next 已经成为内核开发过程中不可或缺的一部分;在一个给定的合并窗口中合并 +的所有补丁都应该在合并窗口打开之前的一段时间内找到进入Linux-next 的方法。 + +Staging 树 +---------- + +内核源代码树包含drivers/staging/目录,其中有许多驱动程序或文件系统的子目录 +正在被添加到内核树中。它们在仍然需要更多的修正的时候可以保留在driver/staging/ +目录中;一旦完成,就可以将它们移到内核中。这是一种跟踪不符合Linux内核编码或 +质量标准的驱动程序的方法,人们可能希望使用它们并跟踪开发。 + +Greg Kroah Hartman 目前负责维护staging 树。仍需要修正的驱动程序将发送给他, +每个驱动程序在drivers/staging/中都有自己的子目录。除了驱动程序源文件之外, +目录中还应该有一个TODO文件。TODO文件列出了驱动程序需要接受的暂停的工作, +以及驱动程序的任何补丁都应该抄送的人员列表。当前的规则要求,staging的驱动 +程序必须至少正确编译。 + +Staging 是一种让新的驱动程序进入主线的相对容易的方法,它们会幸运地引起其他 +开发人员的注意,并迅速改进。然而,进入staging并不是故事的结尾;staging中 +没有看到常规进展的代码最终将被删除。经销商也倾向于相对不愿意使用staging驱动 +程序。因此,在成为一个合适的主线驱动的路上,staging 仅是一个中转站。 + +工具 +---- + +从上面的文本可以看出,内核开发过程在很大程度上依赖于在不同方向上聚集补丁的 +能力。如果没有适当强大的工具,整个系统将无法在任何地方正常工作。关于如何使用 +这些工具的教程远远超出了本文档的范围,但还是用一点篇幅介绍一些关键点。 + +到目前为止,内核社区使用的主要源代码管理系统是git。Git是在自由软件社区中开发 +的许多分布式版本控制系统之一。它非常适合内核开发,因为它在处理大型存储库和 +大量补丁时性能非常好。它也以难以学习和使用而著称,尽管随着时间的推移它变得 +更好了。对于内核开发人员来说,对Git的某种熟悉几乎是一种要求;即使他们不将它 +用于自己的工作,他们也需要Git来跟上其他开发人员(以及主线)正在做的事情。 + +现在几乎所有的Linux发行版都打包了Git。Git主页位于: + + https://git-scm.com/ + +此页面包含了文档和教程的链接。 + +在不使用git的内核开发人员中,最流行的选择几乎肯定是Mercurial: + + http://www.seleric.com/mercurial/ + +Mercurial与Git共享许多特性,但它提供了一个界面,许多人觉得它更易于使用。 + +另一个值得了解的工具是Quilt: + + https://savannah.nongnu.org/projects/quilt + +Quilt 是一个补丁管理系统,而不是源代码管理系统。它不会随着时间的推移跟踪历史; +相反,它面向根据不断发展的代码库跟踪一组特定的更改。一些主要的子系统维护人员 +使用Quilt来管理打算向上游移动的补丁。对于某些树的管理(例如-mm),quilt 是 +最好的工具。 + +邮件列表 +-------- + +大量的Linux内核开发工作是通过邮件列表完成的。如果不加入至少一个某个列表, +就很难成为社区中的一个“全功能”成员。但是,Linux邮件列表对开发人员来说也是 +一个潜在的危险,他们可能会被一堆电子邮件淹没、违反Linux列表上使用的约定, +或者两者兼而有之。 + +大多数内核邮件列表都在vger.kernel.org上运行;主列表位于: + + http://vger.kernel.org/vger-lists.html + +不过,也有一些列表托管在别处;其中一些列表位于 +redhat.com/mailman/listinfo。 + +当然,内核开发的核心邮件列表是linux-kernel。这个列表是一个令人生畏的地方: +每天的信息量可以达到500条,噪音很高,谈话技术性很强,且参与者并不总是表现出 +高度的礼貌。但是,没有其他地方可以让内核开发社区作为一个整体聚集在一起; +不使用此列表的开发人员将错过重要信息。 + +以下一些提示可以帮助在linux-kernel生存: + +- 将邮件转移到单独的文件夹,而不是主邮箱文件夹。我们必须能够持续地忽略洪流。 + +- 不要试图跟上每一次谈话——没人会这样。重要的是要筛选感兴趣的主题(但请注意 + 长时间的对话可能会偏离原来的主题,尽管未改变电子邮件的主题)和参与的人。 + +- 不要回复挑事的人。如果有人试图激起愤怒,请忽略他们。 + +- 当回复Linux内核电子邮件(或其他列表上的电子邮件)时,请为所有相关人员保留 + Cc: 抄送头。如果没有确实的理由(如明确的请求),则不应删除收件人。一定要 + 确保你要回复的人在抄送列表中。这个惯例也使你不必在回复邮件时明确要求被抄送。 + +- 在提出问题之前,搜索列表存档(和整个网络)。有些开发人员可能会对那些显然 + 没有完成家庭作业的人感到不耐烦。 + +- 避免顶部回复(把你的答案放在你要回复的引文上面的做法)。这会让你的回答更难 + 理解,印象也很差。 + +- 在正确的邮件列表发问。linux-kernel 可能是通用的讨论场所,但它不是寻找所有 + 子系统开发人员的最佳场所。 + +最后一点——找到正确的邮件列表——是开发人员常出错的地方。在linux-kernel上 +提出与网络相关的问题的人几乎肯定会收到一个礼貌的建议,转到netdev列表上提出, +因为这是大多数网络开发人员经常出现的列表。还有其他列表可用于scsi、video4linux、 +ide、filesystem等子系统。查找邮件列表的最佳位置是与内核源代码一起打包的 +MAINTAINERS文件。 + +开始内核开发 +------------ + +关于如何开始内核开发过程的问题很常见——个人和公司皆然。同样常见的是失误,这 +使得关系的开始比本应的更困难。 + +公司通常希望聘请知名的开发人员来启动开发团队。实际上,这是一种有效的技术。 +但它也往往是昂贵的,而且对增加有经验的内核开发人员的数量没有多大帮助。考 +虑到时间投入,可以让内部开发人员加快Linux内核的开发速度。利用这段时间可以 +让雇主拥有一批既了解内核又了解公司的开发人员,还可以帮助培训其他人。从中期 +来看,这通常是更有利可图的方法。 + +可以理解的是,单个开发人员往往对起步感到茫然。从一个大型项目开始可能会很 +吓人;人们往往想先用一些较小的东西来试试水。由此,一些开发人员开始创建修补 +拼写错误或轻微编码风格问题的补丁。不幸的是,这样的补丁会产生一定程度的噪音, +这会分散整个开发社区的注意力,因此,它们越来越被人不看重。希望向社区介绍 +自己的新开发人员将无法通过这些方式获得他们期待的反响。 + +Andrew Morton 为有抱负的内核开发人员提供了如下建议 + +:: + + 所有内核开发者的第一个项目肯定应该是“确保内核在您可以操作的所有 + 机器上始终完美运行”。通常的方法是和其他人一起解决问题(这可能需 + 要坚持!),但就是如此——这是内核开发的一部分。 + +(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 0000000000..2caba4753b --- /dev/null +++ b/Documentation/translations/zh_CN/process/3.Early-stage.rst @@ -0,0 +1,168 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/3.Early-stage.rst <development_early_stage>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_early_stage: + +早期规划 +======== + +当考虑一个Linux内核开发项目时,很可能会直接跳进去开始编码。然而,与任何重要 +的项目一样,许多成功的基础最好是在第一行代码编写之前就打下。在早期计划和 +沟通中花费一些时间可以在之后节省更多的时间。 + +搞清问题 +-------- + +与任何工程项目一样,成功的内核改善从清晰描述要解决的问题开始。在某些情况 +下,这个步骤很容易:例如当某个特定硬件需要驱动程序时。不过,在其他情况下, +很容易将实际问题与建议的解决方案混在一起,这可能会导致麻烦。 + +举个例子:几年前,Linux音频的开发人员寻求一种方法来运行应用程序,而不会因 +系统延迟过大而导致退出或其他问题。他们得到的解决方案是一个连接到Linux安全 +模块(LSM)框架中的内核模块;这个模块可以配置为允许特定的应用程序访问实时 +调度程序。这个模块被实现并发到linux-kernel邮件列表,在那里它立即遇到了麻烦。 + +对于音频开发人员来说,这个安全模块足以解决他们当前的问题。但是,对于更广泛的 +内核社区来说,这被视为对LSM框架的滥用(LSM框架并不打算授予他们原本不具备的 +进程特权),并对系统稳定性造成风险。他们首选的解决方案包括短期的通过rlimit +机制进行实时调度访问,以及长期的减少延迟的工作。 + +然而,音频社区无法超越他们实施的特定解决方案来看问题;他们不愿意接受替代方案。 +由此产生的分歧使这些开发人员对整个内核开发过程感到失望;其中一个开发人员返回 +到audio列表并发布了以下内容: + + 有很多非常好的Linux内核开发人员,但他们往往会被一群傲慢的傻瓜所压倒。 + 试图向这些人传达用户需求是浪费时间。他们太“聪明”了,根本听不到少数 + 人的话。 + +(http://lwn.net/Articles/131776/) + +实际情况却是不同的;与特定模块相比,内核开发人员更关心系统稳定性、长期维护 +以及找到问题的正确解决方案。这个故事的寓意是把重点放在问题上——而不是具体的 +解决方案上——并在开始编写代码之前与开发社区讨论这个问题。 + +因此,在考虑一个内核开发项目时,我们应该得到一组简短问题的答案: + + - 需要解决的问题究竟是什么? + + - 受此问题影响的用户有哪些?解决方案应该解决哪些使用案例? + + - 内核现在为何没能解决这个问题? + +只有这样,才能开始考虑可能的解决方案。 + + +早期讨论 +-------- + +在计划内核开发项目时,在开始实施之前与社区进行讨论是很有意义的。早期沟通可以 +通过多种方式节省时间和麻烦: + + - 很可能问题是由内核以您不理解的方式解决的。Linux内核很大,具有许多不明显 + 的特性和功能。并不是所有的内核功能都像人们所希望的那样有文档记录,而且很 + 容易遗漏一些东西。某作者发布了一个完整的驱动程序,重复了一个其不 + 知道的现有驱动程序。重新发明现有轮子的代码不仅浪费,而且不会被接受到主线 + 内核中。 + + - 建议的解决方案中可能有一些要素不适合并入主线。在编写代码之前,最好先了解 + 这样的问题。 + + - 其他开发人员完全有可能考虑过这个问题;他们可能有更好的解决方案的想法,并且 + 可能愿意帮助创建这个解决方案。 + +在内核开发社区的多年经验给了我们一个明确的教训:闭门设计和开发的内核代码总是 +有一些问题,这些问题只有在代码发布到社区中时才会被发现。有时这些问题很严重, +需要数月或数年的努力才能使代码达到内核社区的标准。例如: + + - 设计并实现了单处理器系统的DeviceScape网络栈。只有使其适合于多处理器系统, + 才能将其合并到主线中。在代码中修改锁等等是一项困难的任务;因此,这段代码 + (现在称为mac80211)的合并被推迟了一年多。 + + - Reiser4文件系统包含许多功能,核心内核开发人员认为这些功能应该在虚拟文件 + 系统层中实现。它还包括一些特性,这些特性在不将系统暴露于用户引起的死锁的 + 情况下是不容易实现的。这些问题过迟发现——以及拒绝处理其中一些问题——已经 + 导致Reiser4置身主线内核之外。 + + - Apparmor安全模块以被认为不安全和不可靠的方式使用内部虚拟文件系统数据结构。 + 这种担心(包括其他)使Apparmor多年来无法进入主线。 + +在这些情况下,与内核开发人员的早期讨论,可以避免大量的痛苦和额外的工作。 + +找谁交流? +---------- + +当开发人员决定公开他们的计划时,下一个问题是:我们从哪里开始?答案是找到正确 +的邮件列表和正确的维护者。对于邮件列表,最好的方法是在维护者(MAINTAINERS)文件 +中查找要发布的相关位置。如果有一个合适的子系统列表,那么其上发布通常比在 +linux-kernel上发布更可取;您更有可能接触到在相关子系统中具有专业知识的开发 +人员,并且环境可能具支持性。 + +找到维护人员可能会有点困难。同样,维护者文件是开始的地方。但是,该文件往往不 +是最新的,并且并非所有子系统都在那里显示。实际上,维护者文件中列出的人员可能 +不是当前实际担任该角色的人员。因此,当对联系谁有疑问时,一个有用的技巧是使用 +git(尤其是“git-log”)查看感兴趣的子系统中当前活动的用户。看看谁在写补丁、 +谁会在这些补丁上加上Signed-off-by行签名(如有)。这些人将是帮助新开发项目的 +最佳人选。 + +找到合适的维护者有时是非常具有挑战性的,以至于内核开发人员添加了一个脚本来 +简化这个过程: + +:: + + .../scripts/get_maintainer.pl + +当给定“-f”选项时,此脚本将返回指定文件或目录的当前维护者。如果在命令行上 +给出了一个补丁,它将列出可能接收补丁副本的维护人员。有许多选项可以调节 +get_maintainer.pl搜索维护者的严格程度;请小心使用更激进的选项,因为最终结果 +可能会包括对您正在修改的代码没有真正兴趣的开发人员。 + +如果所有其他方法都失败了,那么与Andrew Morton交流是跟踪特定代码段维护人员 +的一种有效方法。 + +何时邮寄? +---------- + +如果可能的话,在早期阶段发布你的计划只会更有帮助。描述正在解决的问题以及已经 +制定的关于如何实施的任何计划。您可以提供的任何信息都可以帮助开发社区为项目 +提供有用的输入。 + +在这个阶段可能发生的一件令人沮丧的事情不是得到反对意见,而是很少或根本没有 +反馈。令人伤心的事实是:(1)内核开发人员往往很忙;(2)不缺少有宏伟计划但 +代码(甚至代码设想)很少的人去支持他们;(3)没有人有义务审查或评论别人发表 +的想法。除此之外,高层级的设计常常隐藏着一些问题,这些问题只有在有人真正尝试 +实现这些设计时才会被发现;因此,内核开发人员宁愿看到代码。 + +如果发布请求评论(RFC)并没得到什么有用的评论,不要以为这意味着无人对此项目 +有兴趣,同时你也不能假设你的想法没有问题。在这种情况下,最好的做法是继续进 +行,把你的进展随时通知社区。 + +获得官方认可 +----------------------- + +如果您的工作是在公司环境中完成的,就像大多数Linux内核工作一样;显然,在您将 +公司的计划或代码发布到公共邮件列表之前,必须获得有适当权利经理的许可。发布 +不确定是否兼容GPL的代码尤其会带来问题;公司的管理层和法律人员越早能够就发布 +内核开发项目达成一致,对参与的每个人都越好。 + +一些读者可能会认为他们的核心工作是为了支持还没有正式承认存在的产品。将雇主 +的计划公布在公共邮件列表上可能不是一个可行的选择。在这种情况下,有必要考虑 +保密是否真的是必要的;通常不需要把开发计划关在门内。 + +的确,有些情况下一家公司在开发过程的早期无法合法地披露其计划。拥有经验丰富 +的内核开发人员的公司可能选择以开环的方式进行开发,前提是他们以后能够避免 +严重的集成问题。对于没有这种内部专业知识的公司,最好的选择往往是聘请外部 +开发者根据保密协议审查计划。Linux基金会运行了一个NDA程序,旨在帮助解决这种 +情况;更多信息参见: + + http://www.linuxfoundation.org/nda/ + +这种审查通常足以避免以后出现严重问题,而无需公开披露项目。 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 0000000000..7cac9424f5 --- /dev/null +++ b/Documentation/translations/zh_CN/process/4.Coding.rst @@ -0,0 +1,293 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/4.Coding.rst <development_coding>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_coding: + +使代码正确 +====================== + +虽然一个坚实的、面向社区的设计过程有很多值得说道的,但是任何内核开发项目工作 +的证明都反映在代码中。它是将由其他开发人员检查并合并(或不合并)到主线树中 +的代码。所以这段代码的质量决定了项目的最终成功。 + +本节将检查编码过程。我们将从内核开发人员常犯的几种错误开始。然后重点将转移 +到正确的做法和相关有用的工具上。 + +陷阱 +---- + +代码风格 +******** + +内核长期以来都有其标准的代码风格,如 +:ref:`Documentation/translations/zh_CN/process/coding-style.rst <cn_codingstyle>` +中所述。在多数时候,该文档中描述的准则至多被认为是建议性的。因此,内核中存在 +大量不符合代码风格准则的代码。这种代码的存在会给内核开发人员带来两方面的危害。 + +首先,相信内核代码标准并不重要,也不强制执行。但事实上,如果没有按照标准 +编写代码,那么新代码将很难加入到内核中;许多开发人员甚至会在审查代码之前要求 +对代码进行重新格式化。一个像内核这么大的代码库需要一些统一格式的代码,以使 +开发人员能够快速理解其中的任何部分。所以再也经不起奇怪格式的代码的折腾了。 + +内核的代码风格偶尔会与雇主的强制风格发生冲突。在这种情况下,必须在代码合并 +之前遵从内核代码风格。将代码放入内核意味着以多种方式放弃一定程度的控制权—— +包括控制代码样式。 + +另一个危害是认为已经在内核中的代码迫切需要修复代码样式。开发者可能会开始编写 +重新格式化补丁,作为熟悉开发过程的一种方式,或者作为将其名字写入内核变更日志 +的一种方式,或者两者兼而有之。但是纯代码风格的修复被开发社区视为噪音,它们往 +往受到冷遇。因此,最好避免编写这种类型的补丁。在由于其他原因处理一段代码的 +同时顺带修复其样式是很自然的,但是不应该仅为了更改代码样式而更改之。 + +代码风格文档也不应该被视为绝对不可违反的规则。如果有一个足够的理由反对这种 +样式(例如为了80列限制拆分行会导致可读性大大降低),那么就这样做吧。 + +注意您还可以使用 ``clang-format`` 工具来帮助您处理这些规则,快速自动重新格式 +化部分代码,和审阅完整的文件以发现代码样式错误、拼写错误和可能的改进。它还 +可以方便地排序 ``#includes`` 、对齐变量/宏、重排文本和其他类似任务。有关详细 +信息,请参阅文档 :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 KCFLAGS=-W”构建内核以 +获得完整集合。 + +内核提供了几个配置选项,可以打开调试功能;大多数配置选项位于“kernel hacking” +子菜单中。对于任何用于开发或测试目的的内核,都应该启用其中几个选项。特别是, +您应该打开: + + - FRAME_WARN 获取大于给定数量的堆栈帧的警告。 + 这些警告生成的输出可能比较冗长,但您不必担心来自内核其他部分的警告。 + + - DEBUG_OBJECTS 将添加代码以跟踪内核创建的各种对象的生命周期,并在出现问题 + 时发出警告。如果你要添加创建(和导出)关于其自己的复杂对象的子系统,请 + 考虑打开对象调试基础结构的支持。 + + - DEBUG_SLAB 可以发现各种内存分配和使用错误;它应该用于大多数开发内核。 + + - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP 和 DEBUG_MUTEXES 会发现许多常见的 + 锁错误。 + +还有很多其他调试选项,其中一些将在下面讨论。其中一些有显著的性能影响,不应 +一直使用。在学习可用选项上花费一些时间,可能会在短期内得到许多回报。 + +其中一个较重的调试工具是锁检查器或“lockdep”。该工具将跟踪系统中每个锁 +(spinlock或mutex)的获取和释放、获取锁的相对顺序、当前中断环境等等。然后, +它可以确保总是以相同的顺序获取锁,相同的中断假设适用于所有情况等等。换句话 +说,lockdep可以找到许多导致系统死锁的场景。在部署的系统中,这种问题可能会 +很痛苦(对于开发人员和用户而言);LockDep允许提前以自动方式发现问题。具有 +任何类型的非普通锁的代码在提交合并前应在启用lockdep的情况下运行测试。 + +作为一个勤奋的内核程序员,毫无疑问,您将检查任何可能失败的操作(如内存分配) +的返回状态。然而,事实上,最终的故障复现路径可能完全没有经过测试。未测试的 +代码往往会出问题;如果所有这些错误处理路径都被执行了几次,那么您可能对代码 +更有信心。 + +内核提供了一个可以做到这一点的错误注入框架,特别是在涉及内存分配的情况下。 +启用故障注入后,内存分配的可配置失败的百分比;这些失败可以限定在特定的代码 +范围内。在启用了故障注入的情况下运行,程序员可以看到当情况恶化时代码如何响 +应。有关如何使用此工具的详细信息,请参阅 +Documentation/fault-injection/fault-injection.rst。 + +“sparse”静态分析工具可以发现其他类型的错误。sparse可以警告程序员用户空间 +和内核空间地址之间的混淆、大端序与小端序的混淆、在需要一组位标志的地方传递 +整数值等等。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系统的 +交叉编译器: + + https://www.kernel.org/pub/tools/crosstool/ + +花一些时间安装和使用这些编译器将有助于避免以后的尴尬。 + +文档 +---- + +文档通常比内核开发规则更为例外。即便如此,足够的文档将有助于简化将新代码合并 +到内核中的过程,使其他开发人员的生活更轻松,并对您的用户有所帮助。在许多情况 +下,添加文档已基本上是强制性的。 + +任何补丁的第一个文档是其关联的变更日志。日志条目应该描述正在解决的问题、解决 +方案的形式、处理补丁的人员、对性能的任何相关影响,以及理解补丁可能需要的任何 +其他内容。确保变更日志说明了*为什么*补丁值得应用;大量开发者未能提供这些信息。 + +任何添加新用户空间接口的代码——包括新的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 0000000000..6a469e1c7d --- /dev/null +++ b/Documentation/translations/zh_CN/process/5.Posting.rst @@ -0,0 +1,246 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_posting: + +发布补丁 +======== + +您的工作迟早会准备好提交给社区进行审查,并最终包含到主线内核中。毫不稀奇, +内核开发社区已经发展出一套用于发布补丁的约定和过程;遵循这些约定和过程将使 +参与其中的每个人的生活更加轻松。本文档试图描述这些约定的部分细节;更多信息 +也可在以下文档中找到 +:ref:`Documentation/translations/zh_CN/process/submitting-patches.rst <cn_submittingpatches>` +和 :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”行,表明补丁作者。只有当你通过电子邮件发送别人的补丁时,这一行 + 才是必须的,但是为防止疑问加上它也不会有什么坏处。 + + - 一行描述,说明补丁的作用。对于在没有其他上下文的情况下看到该消息的读者来说, + 该消息应足以确定修补程序的范围;此行将显示在“short form(简短格式)”变更 + 日志中。此消息通常需要先加上子系统名称前缀,然后是补丁的目的。例如: + + :: + + gpio: fix build on CONFIG_GPIO_SYSFS=n + + - 一行空白,后接补丁内容的详细描述。此描述可以是任意需要的长度;它应该说明补丁 + 的作用以及为什么它应该应用于内核。 + + - 一个或多个标记行,至少有一个由补丁作者的 Signed-off-by 签名。标记将在下面 + 详细描述。 + +上面的项目一起构成补丁的变更日志。写一则好的变更日志是一门至关重要但常常被 +忽视的艺术;值得花一点时间来讨论这个问题。当你编写变更日志时,你应该记住有 +很多不同的人会读你的话。其中包括子系统维护人员和审查人员,他们需要决定是否 +应该合并补丁,分销商和其他维护人员试图决定是否应该将补丁反向移植到其他内核, +缺陷搜寻人员想知道补丁是否导致他们正在追查的问题,以及想知道内核如何变化的 +用户等等。一个好的变更日志以最直接和最简洁的方式向所有这些人传达所需的信息。 + +在结尾,总结行应该描述变更的影响和动机,以及在一行约束条件下可能发生的变化。 +然后,详细的描述可以详述这些主题,并提供任何需要的附加信息。如果补丁修复了 +一个缺陷,请引用引入该缺陷的提交(如果可能,请在引用提交时同时提供其 id 和 +标题)。如果某个问题与特定的日志或编译器输出相关联,请包含该输出以帮助其他 +人搜索同一问题的解决方案。如果更改是为了支持以后补丁中的其他更改,那么应当 +说明。如果更改了内部API,请详细说明这些更改以及其他开发人员应该如何响应。 +一般来说,你越把自己放在每个阅读你变更日志的人的位置上,变更日志(和内核 +作为一个整体)就越好。 + +不需要说,变更日志是将变更提交到版本控制系统时使用的文本。接下来将是: + + - 补丁本身,采用统一的(“-u”)补丁格式。使用“-p”选项来diff将使函数名与 + 更改相关联,从而使结果补丁更容易被其他人读取。 + +您应该避免在补丁中包括与更改不相关文件(例如,构建过程生成的文件或编辑器 +备份文件)。文档目录中的“dontdiff”文件在这方面有帮助;使用“-X”选项将 +其传递给diff。 + +上面提到的标签(tag)用于描述各种开发人员如何与这个补丁的开发相关联。 +: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: 表示作者身份,所以每个共同开发人,必须紧跟在相关合作作者 + 的Signed-off-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-kernel列表。 + + - 如果您正在修复一个缺陷,请考虑该修复是否应进入下一个稳定更新。如果是这样, + 补丁副本也应发到stable@vger.kernel.org 。另外,在补丁本身的标签中添加一个 + “Cc: stable@vger.kernel.org”;这将使稳定版团队在修复进入主线时收到通知。 + +当为一个补丁选择接收者时,最好清楚你认为谁最终会接受这个补丁并将其合并。虽然 +可以将补丁直接发给Linus Torvalds并让他合并,但通常情况下不会这样做。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 0000000000..2a127e737b --- /dev/null +++ b/Documentation/translations/zh_CN/process/6.Followthrough.rst @@ -0,0 +1,152 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/6.Followthrough.rst <development_followthrough>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_followthrough: + +跟进 +==== + +此时,您已经遵循了到目前为止给出的指导方针,并且,随着您自己的工程技能的增加, +已经发布了一系列完美的补丁。即使是经验丰富的内核开发人员也能犯的最大错误之一 +是,认为他们的工作现在已经完成了。事实上,发布补丁意味着进入流程的下一个阶段, +可能还需要做很多工作。 + +一个补丁在首次发布时就非常出色、没有改进的余地,这是很罕见的。内核开发流程已 +认识到这一事实,因此它非常注重对已发布代码的改进。作为代码的作者,您应该与 +内核社区合作,以确保您的代码符合内核的质量标准。如果不参与这个过程,很可能会 +无法将补丁合并到主线中。 + +与审阅者合作 +------------ + +任何意义上的补丁都会导致其他开发人员在审查代码时发表大量评论。对于许多开发 +人员来说,与审阅人员合作可能是内核开发过程中最令人生畏的部分。但是如果你 +记住一些事情,生活会变得容易得多: + + - 如果你已经很好地解释了你的补丁,审阅人员会理解它的价值,以及为什么你会 + 费尽心思去写它。但是这个并不能阻止他们提出一个基本的问题:在五年或十年后 + 维护含有此代码的内核会怎么样?你可能被要求做出的许多改变——从编码风格的 + 调整到大量的重写——都来自于对Linux的理解,即从现在起十年后,Linux仍将 + 在开发中。 + + - 代码审查是一项艰苦的工作,这是一项相对吃力不讨好的工作;人们记得谁编写了 + 内核代码,但对于那些审查它的人来说,几乎没有什么长久的名声。因此,审阅 + 人员可能会变得暴躁,尤其是当他们看到同样的错误被一遍又一遍地犯下时。如果 + 你得到了一个看起来愤怒、侮辱或完全冒犯你的评论,请抑制以同样方式回应的冲动。 + 代码审查是关于代码的,而不是关于人的,代码审阅人员不会亲自攻击您。 + + - 同样,代码审阅人员也不想以牺牲你雇主的利益为代价来宣传他们雇主的议程。 + 内核开发人员通常希望今后几年能在内核上工作,但他们明白他们的雇主可能会改 + 变。他们真的,几乎毫无例外地,致力于创造他们所能做到的最好的内核;他们并 + 没有试图给雇主的竞争对手造成不适。 + +所有这些归根结底就是,当审阅者向您发送评论时,您需要注意他们正在进行的技术 +评论。不要让他们的表达方式或你自己的骄傲阻止此事。当你在一个补丁上得到评论 +时,花点时间去理解评论人想说什么。如果可能的话,请修复审阅者要求您修复的内 +容。然后回复审阅者:谢谢他们,并描述你将如何回答他们的问题。 + +请注意,您不必同意审阅者建议的每个更改。如果您认为审阅者误解了您的代码,请 +解释到底发生了什么。如果您对建议的更改有技术上的异议,请描述它并证明您对该 +问题的解决方案是正确的。如果你的解释有道理,审阅者会接受的。不过,如果你的 +解释证明缺乏说服力,尤其是当其他人开始同意审稿人的观点时,请花些时间重新考虑 +一下。你很容易对自己解决问题的方法视而不见,以至于你没有意识到某些东西完全 +是错误的,或者你甚至没有解决正确的问题。 + +Andrew Morton建议,每一个不会导致代码更改的审阅评论都应该产生一个额外的代码 +注释;这可以帮助未来的审阅人员避免第一次出现的问题。 + +一个致命的错误是忽视评论,希望它们会消失。它们不会走的。如果您在没有对之前 +收到的评论做出响应的情况下重新发布代码,那么很可能会发现补丁毫无用处。 + +说到重新发布代码:请记住,审阅者不会记住您上次发布的代码的所有细节。因此, +提醒审阅人员以前提出的问题以及您如何处理这些问题总是一个好主意;补丁变更 +日志是提供此类信息的好地方。审阅者不必搜索列表档案来熟悉上次所说的内容; +如果您帮助他们直接开始,当他们重新查看您的代码时,心情会更好。 + +如果你已经试着做正确的事情,但事情仍然没有进展呢?大多数技术上的分歧都可以 +通过讨论来解决,但有时人们仍需要做出决定。如果你真的认为这个决定对你不利, +你可以试着向有更高权力的人上诉。对于本文,更高权力的人是 Andrew Morton 。 +Andrew 在内核开发社区中非常受尊敬;他经常为似乎被绝望阻塞的事情清障。尽管 +如此,不应轻易就直接找 Andrew ,也不应在所有其他替代方案都被尝试之前找他。 +当然,记住,他也可能不同意你的意见。 + +接下来会发生什么 +---------------- + +如果一个补丁被认为适合添加到内核中,并且大多数审查问题得到解决,下一步通常 +是进入子系统维护人员的树中。工作方式因子系统而异;每个维护人员都有自己的 +工作方式。特别是可能有不止一棵树——也许一棵树专门用于计划下一个合并窗口的 +补丁,另一棵树用于长期工作。 + +对于应用到不属于明显子系统树(例如内存管理修补程序)的区域的修补程序,默认树 +通常上溯到-mm。影响多个子系统的补丁也可以最终进入-mm树。 + +包含在子系统树中可以提高补丁的可见性。现在,使用该树的其他开发人员将默认获 +得补丁。子系统树通常也为Linux提供支持,使其内容对整个开发社区可见。在这一点 +上,您很可能会从一组新的审阅者那里得到更多的评论;这些评论需要像上一轮那样 +得到回应。 + +在这时也会发生点什么,这取决于你的补丁的性质,是否与其他人正在做的工作发生 +冲突。在最坏的情况下,严重的补丁冲突可能会导致一些工作被搁置,以便剩余的补丁 +可以成形并合并。另一些时候,冲突解决将涉及到与其他开发人员合作,可能还会 +在树之间移动一些补丁,以确保所有的应用都是干净的。这项工作可能是一件痛苦的 +事情,但也需庆幸现在的幸福:在linux-next树出现之前,这些冲突通常只在合并窗口 +中出现,必须迅速解决。现在可以在合并窗口打开之前的空闲时间解决这些问题。 + +有朝一日,如果一切顺利,您将登录并看到您的补丁已经合并到主线内核中。祝贺你! +然而,一旦庆祝完了(并且您已经将自己添加到维护人员文件中),就一定要记住 +一个重要的小事实:工作仍然没有完成。并入主线也带来了它的挑战。 + +首先,补丁的可见性再次提高。可能会有以前不知道这个补丁的开发者的新一轮评论。 +忽略它们可能很有诱惑力,因为您的代码不再存在任何被合并的问题。但是,要抵制 +这种诱惑,您仍然需要对有问题或建议的开发人员作出响应。 + +不过,更重要的是:将代码包含在主线中会将代码交给更多的一些测试人员。即使您 +为尚未可用的硬件提供了驱动程序,您也会惊讶于有多少人会将您的代码构建到内核 +中。当然,如果有测试人员,也可能会有错误报告。 + +最糟糕的错误报告是回归。如果你的补丁导致回归,你会发现多到让你不舒服的眼睛盯 +着你;回归需要尽快修复。如果您不愿意或无法修复回归(其他人都不会为您修复), +那么在稳定期内,您的补丁几乎肯定会被移除。除了否定您为使补丁进入主线所做的 +所有工作之外,如果由于未能修复回归而取消补丁,很可能会使将来的工作更难被合并。 + +在处理完任何回归之后,可能还有其他普通缺陷需要处理。稳定期是修复这些错误并 +确保代码在主线内核版本中的首次发布尽可能可靠的最好机会。所以,请回应错误 +报告,并尽可能解决问题。这就是稳定期的目的;一旦解决了旧补丁的任何问题,就 +可以开始尽情创建新补丁。 + +别忘了,还有其他节点也可能会创建缺陷报告:下一个主线稳定版本,当著名的发行 +商选择包含您补丁的内核版本时等等。继续响应这些报告是您工作的基本素养。但是 +如果这不能提供足够的动机,那么也需要考虑:开发社区会记住那些在合并后对代码 +失去兴趣的开发人员。下一次你发布补丁时,他们会以你以后不会持续维护它为前提 +来评估它。 + +其他可能发生的事情 +------------------ + +某天,当你打开你的邮件客户端时,看到有人给你寄了一个代码补丁。毕竟,这是 +让您的代码公开存在的好处之一。如果您同意这个补丁,您可以将它转发给子系统 +维护人员(确保包含一个正确的From:行,这样属性是正确的,并添加一个您自己的 +signoff ),或者回复一个 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 0000000000..57beca0218 --- /dev/null +++ b/Documentation/translations/zh_CN/process/7.AdvancedTopics.rst @@ -0,0 +1,133 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>` + +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _cn_development_advancedtopics: + +高级主题 +======== + +现在,希望您能够掌握开发流程的工作方式。然而,还有更多的东西要学!本节将介绍 +一些主题,这些主题对希望成为Linux内核开发过程常规部分的开发人员有帮助。 + +使用Git管理补丁 +--------------- + +内核使用分布式版本控制始于2002年初,当时Linus首次开始使用专有的Bitkeeper应用 +程序。虽然BitKeeper存在争议,但它所体现的软件版本管理方法却肯定不是。分布式 +版本控制可以立即加速内核开发项目。现在有好几种免费的BitKeeper替代品。 +但无论好坏,内核项目都已经选择了Git作为其工具。 + +使用Git管理补丁可以使开发人员的生活更加轻松,尤其是随着补丁数量的增长。Git也 +有其粗糙的边角和一定的危险性,它是一个年轻和强大的工具,仍然在其开发人员完善 +中。本文档不会试图教会读者如何使用git;这会是个巨长的文档。相反,这里的重点 +将是Git如何特别适合内核开发过程。想要加快用Git速度的开发人员可以在以下网站上 +找到更多信息: + + https://git-scm.com/ + + https://www.kernel.org/pub/software/scm/git/docs/user-manual.html + +同时网上也能找到各种各样的教程。 + +在尝试使用它生成补丁供他人使用之前,第一要务是阅读上述网页,对Git的工作方式 +有一个扎实的了解。使用Git的开发人员应能进行拉取主线存储库的副本,查询修订 +历史,提交对树的更改,使用分支等操作。了解Git用于重写历史的工具(如rebase) +也很有用。Git有自己的术语和概念;Git的新用户应该了解引用、远程分支、索引、 +快进合并、推拉、游离头等。一开始可能有点吓人,但这些概念不难通过一点学习来 +理解。 + +使用git生成通过电子邮件提交的补丁是提高速度的一个很好的练习。 + +当您准备好开始建立Git树供其他人查看时,无疑需要一个可以从中拉取的服务器。 +如果您有一个可以访问因特网的系统,那么使用git-daemon设置这样的服务器相对 +简单。同时,免费的公共托管网站(例如github)也开始出现在网络上。成熟的开发 +人员可以在kernel.org上获得一个帐户,但这些帐户并不容易得到;更多有关信息, +请参阅 https://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:”行。 + +请求拉取时,请务必提供所有相关信息:树的位置、要拉取的分支以及拉取将导致的 +更改。在这方面 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 0000000000..643b88af97 --- /dev/null +++ b/Documentation/translations/zh_CN/process/8.Conclusion.rst @@ -0,0 +1,69 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/8.Conclusion.rst <development_conclusion>` +:Translator: + + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com> + +:校译: + + 吴想成 Wu XiangCheng <bobwxc@email.cn> + +.. _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>` +也是所有内核开发人员都应该阅读的内容。许多内部内核API都是使用kerneldoc机制 +记录的;“make htmldocs”或“make pdfdocs”可用于以HTML或PDF格式生成这些文档 +(尽管某些发行版提供的tex版本会遇到内部限制,无法正确处理文档)。 + +不同的网站在各个细节层次上讨论内核开发。本文作者想谦虚地建议用 https://lwn.net/ +作为来源;有关许多特定内核主题的信息可以通过以下网址的 LWN 内核索引找到: + + http://lwn.net/kernel/index/ + +除此之外,内核开发人员的一个宝贵资源是: + + https://kernelnewbies.org/ + +当然,也不应该忘记 https://kernel.org/ ,这是内核发布信息的最终位置。 + +关于内核开发有很多书: + + 《Linux设备驱动程序》第三版(Jonathan Corbet、Alessandro Rubini和Greg Kroah Hartman) + 线上版本在 http://lwn.net/kernel/ldd3/ + + 《Linux内核设计与实现》(Robert Love) + + 《深入理解Linux内核》(Daniel Bovet和Marco Cesati) + +然而,所有这些书都有一个共同的缺点:它们上架时就往往有些过时,而且已经上架 +一段时间了。不过,在那里还是可以找到相当多的好信息。 + +有关git的文档,请访问: + + https://www.kernel.org/pub/software/scm/git/docs/ + + https://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 0000000000..c323ce76e0 --- /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 0000000000..99024df058 --- /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 0000000000..fa28ef0a7f --- /dev/null +++ b/Documentation/translations/zh_CN/process/coding-style.rst @@ -0,0 +1,1083 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: Documentation/process/coding-style.rst + +.. _cn_codingstyle: + +:译者: + - 张乐 Zhang Le <r0bertz@gentoo.org> + - Andy Deng <theandy.deng@gmail.com> + - 吴想成 <bobwxc@email.cn> + +:校译: + - 王聪 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; + fallthrough; + default: + break; + } + +不要把多个语句放在一行里,除非你有什么东西要隐藏: + +.. code-block:: c + + if (condition) do_this; + do_something_everytime; + +不要使用逗号来避免使用大括号: + +.. code-block:: c + + if (condition) + do_this(), do_that(); + +使用大括号包裹多语句: + +.. code-block:: c + + if (condition) { + do_this(); + do_that(); + } + +也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读 +的表达式。 + +除了注释、文档和 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`` 可以用来称呼任意类型的临时变量。 + +如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综 +合征。请看第六章 (函数)。 + +对于符号名称和文档,避免引入新的“master/slave”(或独立于“master”的“slave”) +和“blacklist/whitelist”。 + +“master/slave”推荐替换为: + '{primary,main} / {secondary,replica,subordinate}' + '{initiator,requester} / {target,responder}' + '{controller,host} / {device,worker,proxy}' + 'leader/follower' + 'director/performer' + +“blacklist/whitelist”推荐替换为: + 'denylist/allowlist' + 'blocklist/passlist' + +引入新用法的例外情况是:维护用户空间ABI/API,或更新现有(截至2020年)硬件或 +协议规范的代码时要求这些术语。对于新规范,尽可能将术语的规范用法转换为内核 +编码标准。 + +.. warning:: + 以上主从、黑白名单规则不适用于中文文档,请勿更改中文术语! + +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); + +6.1) 函数原型 +************* + +在函数原型中包含参数名和它们的数据类型。虽然 C 语言里没有这样的要求,但在 +Linux 里这是提倡的做法,因为这样可以很简单的给读者提供更多的有价值的信息。 + +不要在函数声明里使用 ``extern`` 关键字,因为这会导致代码行变长,并且不是严格 +必需的。 + +写函数原型时,请保持 `元素顺序规则 <https://lore.kernel.org/mm-commits/CAHk-=wiOCLRny5aifWNhr621kYrJwhfURsa0vFPeUEm8mF0ufg@mail.gmail.com/>`_ 。 +例如下列函数声明:: + + __init void * __must_check action(enum magic value, size_t size, u8 count, + char *fmt, ...) __printf(4, 5) __malloc; + +推荐的函数原型元素顺序是: + +- 储存类型(下方的 ``static __always_inline`` ,注意 ``__always_inline`` + 技术上来讲是个属性但被当做 ``inline`` ) +- 储存类型属性(上方的 ``__init`` ——即节声明,但也像 ``__cold`` ) +- 返回类型(上方的 ``void *`` ) +- 返回类型属性(上方的 ``__must_check`` ) +- 函数名(上方的 ``action`` ) +- 函数参数(上方的 ``(enum magic value, size_t size, u8 count, char *fmt, ...)`` , + 注意必须写上参数名) +- 函数参数属性(上方的 ``__printf(4, 5)`` ) +- 函数行为属性(上方的 ``__malloc`` ) + +请注意,对于函数 **定义** (即实际函数体),编译器不允许在函数参数之后添加函 +数参数属性。在这种情况下,它们应该跟随存储类型属性(例如,与上面的 **声明** +示例相比,请注意下面的 ``__printf(4, 5)`` 的位置发生了变化):: + + static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value, + size_t size, u8 count, char *fmt, ...) __malloc + { + ... + } + +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/translations/zh_CN/doc-guide/index.rst 和 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:: elisp + + (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`` 不能修正坏的编程习惯。 + +请注意,您还可以使用 ``clang-format`` 工具帮助您处理这些规则,快速自动重新格 +式化部分代码,并审阅整个文件以发现代码风格错误、打字错误和可能的改进。它还可 +以方便地排序 ``#include`` ,对齐变量/宏,重排文本和其他类似任务。 +详见 Documentation/process/clang-format.rst 。 + + +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.rst 。 + + +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 调试选项来开启对应 Makefile 里面的 -DDEBUG;在其他 +情况下,特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时,例如, +如果已经包含一个调试相关的 #ifdef 条件,printk(KERN_DEBUG ...) 就可被使用。 + + +14) 分配内存 +------------ + +内核提供了下面的一般用途的内存分配函数: +kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。 +请参考 API 文档以获取有关它们的详细信息: +Documentation/translations/zh_CN/core-api/memory-allocation.rst 。 + +传递结构体大小的首选形式是这样的: + +.. 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。 + +在没有 __GFP_NOWARN 的情况下使用时,这些通用分配函数都会在失败时发起堆栈转储, +因此当返回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) 使用布尔类型 +---------------- + +Linux内核布尔(bool)类型是C99 _Bool类型的别名。布尔值只能为0或1,而对布尔的 +隐式或显式转换将自动将值转换为true或false。在使用布尔类型时 **不需要** 构造, +它会消除一类错误。 + +使用布尔值时,应使用true和false定义,而不是1和0。 + +布尔函数返回类型和堆栈变量总是可以在适当的时候使用。鼓励使用布尔来提高可读性, +并且布尔值在存储时通常比“int”更好。 + +如果缓存行布局或值的大小很重要,请不要使用布尔,因为其大小和对齐方式根据编译 +的体系结构而不同。针对对齐和大小进行优化的结构体不应使用布尔。 + +如果一个结构体有多个true/false值,请考虑将它们合并为具有1比特成员的位域,或使 +用适当的固定宽度类型,如u8。 + +类似地,对于函数参数,多个true/false值可以合并为单个按位的“标志”参数,如果调 +用点具有裸true/false常量,“标志”参数通常是更具可读性的替代方法。 + +总之,在结构体和参数中有限地使用布尔可以提高可读性。 + +18) 不要重新发明内核宏 +---------------------- + +头文件 include/linux/kernel.h 包含了一些宏,你应该使用它们,而不要自己写一些 +它们的变种。比如,如果你需要计算一个数组的长度,使用这个宏 + +.. code-block:: c + + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +类似的,如果你要计算某结构体成员的大小,使用 + +.. code-block:: c + + #define sizeof_field(t, f) (sizeof(((t*)0)->f)) + +还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以 +自己看看那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应 +在你的代码里自己重新定义。 + + +19) 编辑器模式行和其他需要罗嗦的事情 +------------------------------------ + +有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如,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 */ + +不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置,你的源文件不 +应该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制 +的模式,或者使用其他可以产生正确的缩进的巧妙方法。 + + +20) 内联汇编 +------------ + +在特定架构的代码中,你可能需要内联汇编与 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 */); + + +21) 条件编译 +------------ + +只要可能,就不要在 .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, 2nd Edition +作者:Brian W. Kernighan 和 Denni M. Ritchie. +Prentice Hall, Inc., 1988. +ISBN 0-13-110362-8 (平装), 0-13-110370-9 (精装). + +.. note:: + + 《C程序设计语言(第2版)》 + 作者:[美] Brian W. Kernighan / [美] Dennis M. Ritchie + 译者:徐宝文 / 李志 / 尤晋元(审校) + 出版社:机械工业出版社,2019 + ISBN:9787111617945 + +The Practice of Programming +作者:Brian W. Kernighan 和 Rob Pike. +Addison-Wesley, Inc., 1999. +ISBN 0-201-61586-X. + +.. note:: + + 《程序设计实践》 + 作者:[美] Brian W. Kernighan / [美] Rob Pike + 出版社:机械工业出版社,2005 + ISBN:9787111091578 + + 《程序设计实践》 + 作者:[美] Brian W. Kernighan / Rob Pike + 译者:裘宗燕 + 出版社:机械工业出版社,2000 + ISBN:9787111075738 + +GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent, +都可以从 https://www.gnu.org/manual/ 找到 + +WG14 是 C 语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/ + +内核文档 Documentation/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 0000000000..30cffe66c0 --- /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 0000000000..34d51cdadc --- /dev/null +++ b/Documentation/translations/zh_CN/process/email-clients.rst @@ -0,0 +1,327 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +.. include:: ../disclaimer-zh_CN.rst + +.. _cn_email_clients: + +:Original: Documentation/process/email-clients.rst + +:译者: + - 贾威威 Harry Wei <harryxiyou@gmail.com> + - 时奎亮 Alex Shi <alexs@kernel.org> + - 吴想成 Wu XiangCheng <bobwxc@email.cn> + +:校译: + - 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"。然而,附件一般是不赞成的, +因为这会使补丁的引用部分在评论过程中变的很困难。 + +同时也强烈建议在补丁或其他邮件的正文中使用纯文本格式。https://useplaintext.email +有助于了解如何配置你喜欢的邮件客户端,并在您还没有首选的情况下列出一些推荐的 +客户端。 + +用来发送Linux内核补丁的邮件客户端在发送补丁时应该处于文本的原始状态。例如, +他们不能改变或者删除制表符或者空格,甚至是在每一行的开头或者结尾。 + +不要通过"format=flowed"模式发送补丁。这样会引起不可预期以及有害的断行。 + +不要让你的邮件客户端进行自动换行。这样也会破坏你的补丁。 + +邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码 +方式,如果你使用UTF-8编码方式发送邮件,那么你将会避免一些可能发生的字符集问题。 + +邮件客户端应该生成并且保持“References:”或者“In-Reply-To:”邮件头,这样邮件会话 +就不会中断。 + +复制粘帖(或者剪贴粘帖)通常不能用于补丁,因为制表符会转换为空格。使用xclipboard, +xclip或者xcutsel也许可以,但是最好测试一下或者避免使用复制粘帖。 + +不要在使用PGP/GPG签名的邮件中包含补丁。这样会使得很多脚本不能读取和适用于你的 +补丁。(这个问题应该是可以修复的) + +在给内核邮件列表发送补丁之前,给自己发送一个补丁是个不错的主意,保存接收到的 +邮件,将补丁用'patch'命令打上,如果成功了,再给内核邮件列表发送。 + + +一些邮件客户端提示 +------------------ + +这里给出一些详细的MUA配置提示,可以用于给Linux内核发送补丁。这些并不意味是 +所有的软件包配置总结。 + +说明: + +- TUI = 以文本为基础的用户接口 +- GUI = 图形界面用户接口 + +Alpine (TUI) +************ + +配置选项: + +在 :menuselection:`Sending Preferences` 菜单: + +- :menuselection:`Do Not Send Flowed Text` 必须开启 +- :menuselection:`Strip Whitespace Before Sending` 必须关闭 + +当写邮件时,光标应该放在补丁会出现的地方,然后按下 :kbd:`CTRL-R` 组合键,使指 +定的补丁文件嵌入到邮件中。 + +Claws Mail (GUI) +**************** + +可以用,有人用它成功地发过补丁。 + +用 :menuselection:`Message-->Insert File` (:kbd:`CTRL-I`) 或外置编辑器插入补丁。 + +若要在Claws编辑窗口重修改插入的补丁,需关闭 +:menuselection:`Configuration-->Preferences-->Compose-->Wrapping` +的 `Auto wrapping` 。 + +Evolution (GUI) +*************** + +一些开发者成功的使用它发送补丁。 + +撰写邮件时: +从 :menuselection:`格式-->段落样式-->预格式化` (:kbd:`CTRL-7`) +或工具栏选择 :menuselection:`预格式化` ; + +然后使用: +:menuselection:`插入-->文本文件...` (:kbd:`ALT-N x`) 插入补丁文件。 + +你还可以 ``diff -Nru old.c new.c | xclip`` ,选择 :menuselection:`预格式化` , +然后使用鼠标中键进行粘帖。 + +Kmail (GUI) +*********** + +一些开发者成功的使用它发送补丁。 + +默认撰写设置禁用HTML格式是合适的;不要启用它。 + +当书写一封邮件的时候,在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输 +入的任何文本都不会被自动换行,因此你必须在发送补丁之前手动换行。最简单的方法 +就是启用自动换行来书写邮件,然后把它保存为草稿。一旦你在草稿中再次打开它,它 +已经全部自动换行了,那么你的邮件虽然没有选择自动换行,但是还不会失去已有的自 +动换行。 + +在邮件的底部,插入补丁之前,放上常用的补丁定界符:三个连字符(``---``)。 + +然后在 :menuselection:`信件` 菜单,选择 :menuselection:`插入文本文件` ,接 +着选取你的补丁文件。还有一个额外的选项,你可以通过它配置你的创建新邮件工具栏, +加上 :menuselection:`插入文本文件` 图标。 + +将编辑器窗口拉到足够宽避免折行。对于KMail 1.13.5 (KDE 4.5.4),它会在发送邮件 +时对编辑器窗口中显示折行的地方自动换行。在选项菜单中取消自动换行仍不能解决。 +因此,如果你的补丁中有非常长的行,必须在发送之前把编辑器窗口拉得非常宽。 +参见:https://bugs.kde.org/show_bug.cgi?id=174034 + +你可以安全地用GPG签名附件,但是内嵌补丁最好不要使用GPG签名它们。作为内嵌文本 +插入的签名补丁将使其难以从7-bit编码中提取。 + +如果你非要以附件的形式发送补丁,那么就右键点击附件,然后选择 +:menuselection:`属性` ,打开 :menuselection:`建议自动显示` ,使附件内联更容 +易让读者看到。 + +当你要保存将要发送的内嵌文本补丁,你可以从消息列表窗格选择包含补丁的邮件,然 +后右键选择 :menuselection:`另存为` 。如果整个电子邮件的组成正确,您可直接将 +其作为补丁使用。电子邮件以当前用户可读写权限保存,因此您必须 ``chmod`` ,以 +使其在复制到别处时用户组和其他人可读。 + +Lotus Notes (GUI) +***************** + +不要使用它。 + +IBM Verse (Web GUI) +******************* + +同上条。 + +Mutt (TUI) +********** + +很多Linux开发人员使用mutt客户端,这证明它肯定工作得非常漂亮。 + +Mutt不自带编辑器,所以不管你使用什么编辑器,不自动断行就行。大多数编辑器都有 +:menuselection:`插入文件` 选项,它可以在不改变文件内容的情况下插入文件。 + +用 ``vim`` 作为mutt的编辑器:: + + set editor="vi" + +如果使用xclip,敲入以下命令:: + + :set paste + +然后再按中键或者shift-insert或者使用:: + + :r filename + +把补丁插入为内嵌文本。 +在未设置 ``set paste`` 时(a)ttach工作的很好。 + +你可以通过 ``git format-patch`` 生成补丁,然后用 Mutt发送它们:: + + $ mutt -H 0001-some-bug-fix.patch + +配置选项: + +它应该以默认设置的形式工作。 +然而,把 ``send_charset`` 设置一下也是一个不错的主意:: + + set 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文档含有更多信息: + + https://gitlab.com/muttmua/mutt/-/wikis/UseCases/Gmail + + http://www.mutt.org/doc/manual/ + +Pine (TUI) +********** + +Pine过去有一些空格删减问题,但是这些现在应该都被修复了。 + +如果可以,请使用alpine(pine的继承者)。 + +配置选项: + +- 最近的版本需要 ``quell-flowed-text`` +- ``no-strip-whitespace-before-send`` 选项也是需要的。 + + +Sylpheed (GUI) +************** + +- 内嵌文本可以很好的工作(或者使用附件)。 +- 允许使用外部的编辑器。 +- 收件箱较多时非常慢。 +- 如果通过non-SSL连接,无法使用TLS SMTP授权。 +- 撰写窗口的标尺很有用。 +- 将地址添加到通讯簿时无法正确理解显示的名称。 + +Thunderbird (GUI) +***************** + +Thunderbird是Outlook的克隆版本,它很容易损坏文本,但也有一些方法强制修正。 + +在完成修改后(包括安装扩展),您需要重新启动Thunderbird。 + +- 允许使用外部编辑器: + + 使用Thunderbird发补丁最简单的方法是使用扩展来打开您最喜欢的外部编辑器。 + + 下面是一些能够做到这一点的扩展样例。 + + - “External Editor Revived” + + https://github.com/Frederick888/external-editor-revived + + https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/ + + 它需要安装“本地消息主机(native messaging host)”。 + 参见以下文档: + https://github.com/Frederick888/external-editor-revived/wiki + + - “External Editor” + + https://github.com/exteditor/exteditor + + 下载并安装此扩展,然后打开 :menuselection:`新建消息` 窗口, 用 + :menuselection:`查看-->工具栏-->自定义...` 给它增加一个按钮,直接点击此 + 按钮即可使用外置编辑器。 + + 请注意,“External Editor”要求你的编辑器不能fork,换句话说,编辑器必须在 + 关闭前不返回。你可能需要传递额外的参数或修改编辑器设置。最值得注意的是, + 如果您使用的是gvim,那么您必须将 :menuselection:`external editor` 设置的 + 编辑器字段设置为 ``/usr/bin/gvim --nofork"`` (假设可执行文件在 + ``/usr/bin`` ),以传递 ``-f`` 参数。如果您正在使用其他编辑器,请阅读其 + 手册了解如何处理。 + +若要修正内部编辑器,请执行以下操作: + +- 修改你的Thunderbird设置,不要使用 ``format=flowed`` ! + 回到主窗口,按照 + :menuselection:`主菜单-->首选项-->常规-->配置编辑器...` + 打开Thunderbird的配置编辑器。 + + - 将 ``mailnews.send_plaintext_flowed`` 设为 ``false`` + + - 将 ``mailnews.wraplength`` 从 ``72`` 改为 ``0`` + +- 不要写HTML邮件! + 回到主窗口,打开 + :menuselection:`主菜单-->账户设置-->你的@邮件.地址-->通讯录/编写&地址簿` , + 关掉 ``以HTML格式编写消息`` 。 + +- 只用纯文本格式查看邮件! + 回到主窗口, :menuselection:`主菜单-->查看-->消息体为-->纯文本` ! + +TkRat (GUI) +*********** + +可以使用它。使用"Insert file..."或者外部的编辑器。 + +Gmail (Web GUI) +*************** + +不要使用它发送补丁。 + +Gmail网页客户端自动地把制表符转换为空格。 + +虽然制表符转换为空格问题可以被外部编辑器解决,但它同时还会使用回车换行把每行 +拆分为78个字符。 + +另一个问题是Gmail还会把任何含有非ASCII的字符的消息改用base64编码,如欧洲人的 +名字。 + diff --git a/Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst new file mode 100644 index 0000000000..cf5f1fca3d --- /dev/null +++ b/Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst @@ -0,0 +1,228 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst <embargoed_hardware_issues>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +被限制的硬件问题 +================ + +范围 +---- + +导致安全问题的硬件问题与只影响Linux内核的纯软件错误是不同的安全错误类别。 + +必须区别对待诸如熔毁(Meltdown)、Spectre、L1TF等硬件问题,因为它们通常会影响 +所有操作系统(“OS”),因此需要在不同的OS供应商、发行版、硬件供应商和其他各方 +之间进行协调。对于某些问题,软件缓解可能依赖于微码或固件更新,这需要进一步的 +协调。 + +.. _zh_Contact: + +接触 +---- + +Linux内核硬件安全小组独立于普通的Linux内核安全小组。 + +该小组只负责协调被限制的硬件安全问题。Linux内核中纯软件安全漏洞的报告不由该 +小组处理,报告者将被引导至常规Linux内核安全小组(:ref:`Documentation/admin-guide/ +<securitybugs>`)联系。 + +可以通过电子邮件 <hardware-security@kernel.org> 与小组联系。这是一份私密的安全 +官名单,他们将帮助您根据我们的文档化流程协调问题。 + +邮件列表是加密的,发送到列表的电子邮件可以通过PGP或S/MIME加密,并且必须使用报告 +者的PGP密钥或S/MIME证书签名。该列表的PGP密钥和S/MIME证书可从 +https://www.kernel.org/.... 获得。 + +虽然硬件安全问题通常由受影响的硬件供应商处理,但我们欢迎发现潜在硬件缺陷的研究 +人员或个人与我们联系。 + +硬件安全官 +^^^^^^^^^^ + +目前的硬件安全官小组: + + - Linus Torvalds(Linux基金会院士) + - Greg Kroah Hartman(Linux基金会院士) + - Thomas Gleixner(Linux基金会院士) + +邮件列表的操作 +^^^^^^^^^^^^^^ + +处理流程中使用的加密邮件列表托管在Linux Foundation的IT基础设施上。通过提供这项 +服务,Linux基金会的IT基础设施安全总监在技术上有能力访问被限制的信息,但根据他 +的雇佣合同,他必须保密。Linux基金会的IT基础设施安全总监还负责 kernel.org 基础 +设施。 + +Linux基金会目前的IT基础设施安全总监是 Konstantin Ryabitsev。 + +保密协议 +-------- + +Linux内核硬件安全小组不是正式的机构,因此无法签订任何保密协议。核心社区意识到 +这些问题的敏感性,并提供了一份谅解备忘录。 + +谅解备忘录 +---------- + +Linux内核社区深刻理解在不同操作系统供应商、发行商、硬件供应商和其他各方之间 +进行协调时,保持硬件安全问题处于限制状态的要求。 + +Linux内核社区在过去已经成功地处理了硬件安全问题,并且有必要的机制允许在限制 +限制下进行符合社区的开发。 + +Linux内核社区有一个专门的硬件安全小组负责初始联系,并监督在限制规则下处理 +此类问题的过程。 + +硬件安全小组确定开发人员(领域专家),他们将组成特定问题的初始响应小组。最初 +的响应小组可以引入更多的开发人员(领域专家)以最佳的技术方式解决这个问题。 + +所有相关开发商承诺遵守限制规定,并对收到的信息保密。违反承诺将导致立即从当前 +问题中排除,并从所有相关邮件列表中删除。此外,硬件安全小组还将把违反者排除在 +未来的问题之外。这一后果的影响在我们社区是一种非常有效的威慑。如果发生违规 +情况,硬件安全小组将立即通知相关方。如果您或任何人发现潜在的违规行为,请立即 +向硬件安全人员报告。 + +流程 +^^^^ + +由于Linux内核开发的全球分布式特性,面对面的会议几乎不可能解决硬件安全问题。 +由于时区和其他因素,电话会议很难协调,只能在绝对必要时使用。加密电子邮件已被 +证明是解决此类问题的最有效和最安全的通信方法。 + +开始披露 +"""""""" + +披露内容首先通过电子邮件联系Linux内核硬件安全小组。此初始联系人应包含问题的 +描述和任何已知受影响硬件的列表。如果您的组织制造或分发受影响的硬件,我们建议 +您也考虑哪些其他硬件可能会受到影响。 + +硬件安全小组将提供一个特定于事件的加密邮件列表,用于与报告者进行初步讨论、 +进一步披露和协调。 + +硬件安全小组将向披露方提供一份开发人员(领域专家)名单,在与开发人员确认他们 +将遵守本谅解备忘录和文件化流程后,应首先告知开发人员有关该问题的信息。这些开发 +人员组成初始响应小组,并在初始接触后负责处理问题。硬件安全小组支持响应小组, +但不一定参与缓解开发过程。 + +虽然个别开发人员可能通过其雇主受到保密协议的保护,但他们不能以Linux内核开发 +人员的身份签订个别保密协议。但是,他们将同意遵守这一书面程序和谅解备忘录。 + +披露方应提供已经或应该被告知该问题的所有其他实体的联系人名单。这有几个目的: + + - 披露的实体列表允许跨行业通信,例如其他操作系统供应商、硬件供应商等。 + + - 可联系已披露的实体,指定应参与缓解措施开发的专家。 + + - 如果需要处理某一问题的专家受雇于某一上市实体或某一上市实体的成员,则响应 + 小组可要求该实体披露该专家。这确保专家也是实体反应小组的一部分。 + +披露 +"""" + +披露方通过特定的加密邮件列表向初始响应小组提供详细信息。 + +根据我们的经验,这些问题的技术文档通常是一个足够的起点,最好通过电子邮件进行 +进一步的技术澄清。 + +缓解开发 +"""""""" + +初始响应小组设置加密邮件列表,或在适当的情况下重新修改现有邮件列表。 + +使用邮件列表接近于正常的Linux开发过程,并且在过去已经成功地用于为各种硬件安全 +问题开发缓解措施。 + +邮件列表的操作方式与正常的Linux开发相同。发布、讨论和审查修补程序,如果同意, +则应用于非公共git存储库,参与开发人员只能通过安全连接访问该存储库。存储库包含 +针对主线内核的主开发分支,并根据需要为稳定的内核版本提供向后移植分支。 + +最初的响应小组将根据需要从Linux内核开发人员社区中确定更多的专家。引进专家可以 +在开发过程中的任何时候发生,需要及时处理。 + +如果专家受雇于披露方提供的披露清单上的实体或其成员,则相关实体将要求其参与。 + +否则,披露方将被告知专家参与的情况。谅解备忘录涵盖了专家,要求披露方确认参与。 +如果披露方有令人信服的理由提出异议,则必须在五个工作日内提出异议,并立即与事件 +小组解决。如果披露方在五个工作日内未作出回应,则视为默许。 + +在确认或解决异议后,专家由事件小组披露,并进入开发过程。 + +协调发布 +"""""""" + +有关各方将协商限制结束的日期和时间。此时,准备好的缓解措施集成到相关的内核树中 +并发布。 + +虽然我们理解硬件安全问题需要协调限制时间,但限制时间应限制在所有有关各方制定、 +测试和准备缓解措施所需的最短时间内。人为地延长限制时间以满足会议讨论日期或其他 +非技术原因,会给相关的开发人员和响应小组带来了更多的工作和负担,因为补丁需要 +保持最新,以便跟踪正在进行的上游内核开发,这可能会造成冲突的更改。 + +CVE分配 +""""""" + +硬件安全小组和初始响应小组都不分配CVE,开发过程也不需要CVE。如果CVE是由披露方 +提供的,则可用于文档中。 + +流程专使 +-------- + +为了协助这一进程,我们在各组织设立了专使,他们可以回答有关报告流程和进一步处理 +的问题或提供指导。专使不参与特定问题的披露,除非响应小组或相关披露方提出要求。 +现任专使名单: + + ============= ======================================================== + ARM + AMD Tom Lendacky <thomas.lendacky@amd.com> + IBM + Intel Tony Luck <tony.luck@intel.com> + Qualcomm Trilok Soni <tsoni@codeaurora.org> + + Microsoft Sasha Levin <sashal@kernel.org> + VMware + Xen Andrew Cooper <andrew.cooper3@citrix.com> + + Canonical John Johansen <john.johansen@canonical.com> + Debian Ben Hutchings <ben@decadent.org.uk> + Oracle Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> + Red Hat Josh Poimboeuf <jpoimboe@redhat.com> + SUSE Jiri Kosina <jkosina@suse.cz> + + Amazon + Google Kees Cook <keescook@chromium.org> + ============= ======================================================== + +如果要将您的组织添加到专使名单中,请与硬件安全小组联系。被提名的专使必须完全 +理解和支持我们的过程,并且在Linux内核社区中很容易联系。 + +加密邮件列表 +------------ + +我们使用加密邮件列表进行通信。这些列表的工作原理是,发送到列表的电子邮件使用 +列表的PGP密钥或列表的/MIME证书进行加密。邮件列表软件对电子邮件进行解密,并 +使用订阅者的PGP密钥或S/MIME证书为每个订阅者分别对其进行重新加密。有关邮件列表 +软件和用于确保列表安全和数据保护的设置的详细信息,请访问: +https://www.kernel.org/.... + +关键点 +^^^^^^ + +初次接触见 :ref:`zh_Contact`. 对于特定于事件的邮件列表,密钥和S/MIME证书通过 +特定列表发送的电子邮件传递给订阅者。 + +订阅事件特定列表 +^^^^^^^^^^^^^^^^ + +订阅由响应小组处理。希望参与通信的披露方将潜在订户的列表发送给响应组,以便 +响应组可以验证订阅请求。 + +每个订户都需要通过电子邮件向响应小组发送订阅请求。电子邮件必须使用订阅服务器 +的PGP密钥或S/MIME证书签名。如果使用PGP密钥,则必须从公钥服务器获得该密钥, +并且理想情况下该密钥连接到Linux内核的PGP信任网。另请参见: +https://www.kernel.org/signature.html. + +响应小组验证订阅者,并将订阅者添加到列表中。订阅后,订阅者将收到来自邮件列表 +的电子邮件,该邮件列表使用列表的PGP密钥或列表的/MIME证书签名。订阅者的电子邮件 +客户端可以从签名中提取PGP密钥或S/MIME证书,以便订阅者可以向列表发送加密电子 +邮件。 diff --git a/Documentation/translations/zh_CN/process/howto.rst b/Documentation/translations/zh_CN/process/howto.rst new file mode 100644 index 0000000000..cc47be356d --- /dev/null +++ b/Documentation/translations/zh_CN/process/howto.rst @@ -0,0 +1,495 @@ +.. _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 C11标准,但也用到了一些 +标准中没有定义的扩展。内核是自给自足的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的常见问题和解答,请访问以下链接: + https://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>` + + 这两份文档明确描述如何创建和发送补丁,其中包括(但不仅限于): + - 邮件内容 + - 邮件格式 + - 选择收件人 + + 遵守这些规定并不能保证提交成功(因为所有补丁需要通过严格的内容和风格 + 审查),但是忽视他们几乎就意味着失败。 + + 其他关于如何正确地生成补丁的优秀文档包括: + "The Perfect Patch" + + https://www.ozlabs.org/~akpm/stuff/tpp.txt + + "Linux kernel patch submission format" + + https://web.archive.org/web/20180829112450/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/process/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>` + 关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍 + +内核还拥有大量从代码自动生成或者从 ReStructuredText(ReST) 标记生成的文档, +比如这个文档,它包含内核内部API的全面介绍以及如何妥善处理加锁的规则。所有 +这些文档都可以通过运行以下命令从内核代码中生成为PDF或HTML文档:: + + make pdfdocs + make htmldocs + +ReST格式的文档会生成在 Documentation/output. 目录中。 +它们也可以用下列命令生成 LaTeX 和 ePub 格式文档:: + + make latexdocs + make epubdocs + +如何成为内核开发者 +------------------ +如果你对Linux内核开发一无所知,你应该访问“Linux内核新手”计划: + + https://kernelnewbies.org + +它拥有一个可以问各种最基本的内核开发问题的邮件列表(在提问之前一定要记得 +查找已往的邮件,确认是否有人已经回答过相同的问题)。它还拥有一个可以获得 +实时反馈的IRC聊天频道,以及大量对于学习Linux内核开发相当有帮助的文档。 + +网站简要介绍了源代码组织结构、子系统划分以及目前正在进行的项目(包括内核 +中的和单独维护的)。它还提供了一些基本的帮助信息,比如如何编译内核和打补 +丁。 + +如果你想加入内核开发社区并协助完成一些任务,却找不到从哪里开始,可以访问 +“Linux内核房管员”计划: + + https://kernelnewbies.org/KernelJanitors + +这是极佳的起点。它提供一个相对简单的任务列表,列出内核代码中需要被重新 +整理或者改正的地方。通过和负责这个计划的开发者们一同工作,你会学到将补丁 +集成进内核的基本原理。如果还没有决定下一步要做什么的话,你还可能会得到方 +向性的指点。 + +在真正动手修改内核代码之前,理解要修改的代码如何运作是必需的。要达到这个 +目的,没什么办法比直接读代码更有效了(大多数花招都会有相应的注释),而且 +一些特制的工具还可以提供帮助。例如,“Linux代码交叉引用”项目就是一个值得 +特别推荐的帮助工具,它将源代码显示在有编目和索引的网页上。其中一个更新及 +时的内核源码库,可以通过以下地址访问: + + https://elixir.bootlin.com/ + + +开发流程 +-------- + +目前Linux内核开发流程包括几个“主内核分支”和很多子系统相关的内核分支。这 +些分支包括: + + - Linus 的内核源码树 + - 多个主要版本的稳定版内核树 + - 子系统相关的内核树 + - linux-next 集成测试树 + + +主线树 +------ +主线树是由Linus Torvalds 维护的。你可以在https://kernel.org 网站或者代码 +库中下找到它。它的开发遵循以下步骤: + + - 每当一个新版本的内核被发布,为期两周的集成窗口将被打开。在这段时间里 + 维护者可以向Linus提交大段的修改,通常这些修改已经被放到-mm内核中几个 + 星期了。提交大量修改的首选方式是使用git工具(内核的代码版本管理工具 + ,更多的信息可以在 https://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)。可以使用搜索引擎来找到这些 +存档。比如: + + https://lore.kernel.org/lkml/ + +在发信之前,我们强烈建议你先在存档中搜索你想要讨论的问题。很多已经被详细 +讨论过的问题只在邮件列表的存档中可以找到。 + +大多数内核子系统也有自己独立的邮件列表来协调各自的开发工作。从 +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” + https://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 0000000000..a1a35f88f4 --- /dev/null +++ b/Documentation/translations/zh_CN/process/index.rst @@ -0,0 +1,63 @@ +.. 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 + kernel-enforcement-statement + kernel-driver-statement + +其它大多数开发人员感兴趣的社区指南: + + +.. toctree:: + :maxdepth: 1 + + submit-checklist + stable-api-nonsense + stable-kernel-rules + management-style + embargoed-hardware-issues + +这些是一些总体性技术指南,由于不大好分类而放在这里: + +.. toctree:: + :maxdepth: 1 + + magic-number + volatile-considered-harmful + +.. only:: subproject and html + + 目录 + ==== + + * :ref:`genindex` diff --git a/Documentation/translations/zh_CN/process/kernel-driver-statement.rst b/Documentation/translations/zh_CN/process/kernel-driver-statement.rst new file mode 100644 index 0000000000..2b3375bccc --- /dev/null +++ b/Documentation/translations/zh_CN/process/kernel-driver-statement.rst @@ -0,0 +1,199 @@ +.. _cn_process_statement_driver: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/kernel-driver-statement.rst <process_statement_driver>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +内核驱动声明 +------------ + +关于Linux内核模块的立场声明 +=========================== + +我们,以下署名的Linux内核开发人员,认为任何封闭源Linux内核模块或驱动程序都是 +有害的和不可取的。我们已经一再发现它们对Linux用户,企业和更大的Linux生态系统 +有害。这样的模块否定了Linux开发模型的开放性,稳定性,灵活性和可维护性,并使 +他们的用户无法使用Linux社区的专业知识。提供闭源内核模块的供应商迫使其客户 +放弃Linux的主要优势或选择新的供应商。因此,为了充分利用开源所提供的成本节省和 +共享支持优势,我们敦促供应商采取措施,以开源内核代码在Linux上为其客户提供支持。 + +我们只为自己说话,而不是我们今天可能会为之工作,过去或将来会为之工作的任何公司。 + + - Dave Airlie + - Nick Andrew + - Jens Axboe + - Ralf Baechle + - Felipe Balbi + - Ohad Ben-Cohen + - Muli Ben-Yehuda + - Jiri Benc + - Arnd Bergmann + - Thomas Bogendoerfer + - Vitaly Bordug + - James Bottomley + - Josh Boyer + - Neil Brown + - Mark Brown + - David Brownell + - Michael Buesch + - Franck Bui-Huu + - Adrian Bunk + - François Cami + - Ralph Campbell + - Luiz Fernando N. Capitulino + - Mauro Carvalho Chehab + - Denis Cheng + - Jonathan Corbet + - Glauber Costa + - Alan Cox + - Magnus Damm + - Ahmed S. Darwish + - Robert P. J. Day + - Hans de Goede + - Arnaldo Carvalho de Melo + - Helge Deller + - Jean Delvare + - Mathieu Desnoyers + - Sven-Thorsten Dietrich + - Alexey Dobriyan + - Daniel Drake + - Alex Dubov + - Randy Dunlap + - Michael Ellerman + - Pekka Enberg + - Jan Engelhardt + - Mark Fasheh + - J. Bruce Fields + - Larry Finger + - Jeremy Fitzhardinge + - Mike Frysinger + - Kumar Gala + - Robin Getz + - Liam Girdwood + - Jan-Benedict Glaw + - Thomas Gleixner + - Brice Goglin + - Cyrill Gorcunov + - Andy Gospodarek + - Thomas Graf + - Krzysztof Halasa + - Harvey Harrison + - Stephen Hemminger + - Michael Hennerich + - Tejun Heo + - Benjamin Herrenschmidt + - Kristian Høgsberg + - Henrique de Moraes Holschuh + - Marcel Holtmann + - Mike Isely + - Takashi Iwai + - Olof Johansson + - Dave Jones + - Jesper Juhl + - Matthias Kaehlcke + - Kenji Kaneshige + - Jan Kara + - Jeremy Kerr + - Russell King + - Olaf Kirch + - Roel Kluin + - Hans-Jürgen Koch + - Auke Kok + - Peter Korsgaard + - Jiri Kosina + - Aaro Koskinen + - Mariusz Kozlowski + - Greg Kroah-Hartman + - Michael Krufky + - Aneesh Kumar + - Clemens Ladisch + - Christoph Lameter + - Gunnar Larisch + - Anders Larsen + - Grant Likely + - John W. Linville + - Yinghai Lu + - Tony Luck + - Pavel Machek + - Matt Mackall + - Paul Mackerras + - Roland McGrath + - Patrick McHardy + - Kyle McMartin + - Paul Menage + - Thierry Merle + - Eric Miao + - Akinobu Mita + - Ingo Molnar + - James Morris + - Andrew Morton + - Paul Mundt + - Oleg Nesterov + - Luca Olivetti + - S.Çağlar Onur + - Pierre Ossman + - Keith Owens + - Venkatesh Pallipadi + - Nick Piggin + - Nicolas Pitre + - Evgeniy Polyakov + - Richard Purdie + - Mike Rapoport + - Sam Ravnborg + - Gerrit Renker + - Stefan Richter + - David Rientjes + - Luis R. Rodriguez + - Stefan Roese + - Francois Romieu + - Rami Rosen + - Stephen Rothwell + - Maciej W. Rozycki + - Mark Salyzyn + - Yoshinori Sato + - Deepak Saxena + - Holger Schurig + - Amit Shah + - Yoshihiro Shimoda + - Sergei Shtylyov + - Kay Sievers + - Sebastian Siewior + - Rik Snel + - Jes Sorensen + - Alexey Starikovskiy + - Alan Stern + - Timur Tabi + - Hirokazu Takata + - Eliezer Tamir + - Eugene Teo + - Doug Thompson + - FUJITA Tomonori + - Dmitry Torokhov + - Marcelo Tosatti + - Steven Toth + - Theodore Tso + - Matthias Urlichs + - Geert Uytterhoeven + - Arjan van de Ven + - Ivo van Doorn + - Rik van Riel + - Wim Van Sebroeck + - Hans Verkuil + - Horst H. von Brand + - Dmitri Vorobiev + - Anton Vorontsov + - Daniel Walker + - Johannes Weiner + - Harald Welte + - Matthew Wilcox + - Dan J. Williams + - Darrick J. Wong + - David Woodhouse + - Chris Wright + - Bryan Wu + - Rafael J. Wysocki + - Herbert Xu + - Vlad Yasevich + - Peter Zijlstra + - Bartlomiej Zolnierkiewicz diff --git a/Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst new file mode 100644 index 0000000000..75f7b7b913 --- /dev/null +++ b/Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst @@ -0,0 +1,151 @@ +.. _cn_process_statement_kernel: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst <process_statement_kernel>` +:Translator: Alex Shi <alex.shi@linux.alibaba.com> + +Linux 内核执行声明 +------------------ + +作为Linux内核的开发人员,我们对如何使用我们的软件以及如何实施软件许可证有着 +浓厚的兴趣。遵守GPL-2.0的互惠共享义务对我们软件和社区的长期可持续性至关重要。 + +虽然有权强制执行对我们社区的贡献中的单独版权权益,但我们有共同的利益,即确保 +个人强制执行行动的方式有利于我们的社区,不会对我们软件生态系统的健康和增长 +产生意外的负面影响。为了阻止无益的执法行动,我们同意代表我们自己和我们版权 +利益的任何继承人对Linux内核用户作出以下符合我们开发社区最大利益的承诺: + + 尽管有GPL-2.0的终止条款,我们同意,采用以下GPL-3.0条款作为我们许可证下的 + 附加许可,作为任何对许可证下权利的非防御性主张,这符合我们开发社区的最佳 + 利益。 + + 但是,如果您停止所有违反本许可证的行为,则您从特定版权持有人处获得的 + 许可证将被恢复:(a)暂时恢复,除非版权持有人明确并最终终止您的许可证; + 以及(b)永久恢复, 如果版权持有人未能在你终止违反后60天内以合理方式 + 通知您违反本许可证的行为,则永久恢复您的许可证。 + + 此外,如果版权所有者以某种合理的方式通知您违反了本许可,这是您第一次 + 从该版权所有者处收到违反本许可的通知(对于任何作品),并且您在收到通知 + 后的30天内纠正违规行为。则您从特定版权所有者处获得的许可将永久恢复. + +我们提供这些保证的目的是鼓励更多地使用该软件。我们希望公司和个人使用、修改和 +分发此软件。我们希望以公开和透明的方式与用户合作,以消除我们对法规遵从性或强制 +执行的任何不确定性,这些不确定性可能会限制我们软件的采用。我们将法律行动视为 +最后手段,只有在其他社区努力未能解决这一问题时才采取行动。 + +最后,一旦一个不合规问题得到解决,我们希望用户会感到欢迎,加入我们为之努力的 +这个项目。共同努力,我们会更强大。 + +除了下面提到的以外,我们只为自己说话,而不是为今天、过去或将来可能为之工作的 +任何公司说话。 + + - Laura Abbott + - Bjorn Andersson (Linaro) + - Andrea Arcangeli + - Neil Armstrong + - Jens Axboe + - Pablo Neira Ayuso + - Khalid Aziz + - Ralf Baechle + - Felipe Balbi + - Arnd Bergmann + - Ard Biesheuvel + - Tim Bird + - Paolo Bonzini + - Christian Borntraeger + - Mark Brown (Linaro) + - Paul Burton + - Javier Martinez Canillas + - Rob Clark + - Kees Cook (Google) + - Jonathan Corbet + - Dennis Dalessandro + - Vivien Didelot (Savoir-faire Linux) + - Hans de Goede + - Mel Gorman (SUSE) + - Sven Eckelmann + - Alex Elder (Linaro) + - Fabio Estevam + - Larry Finger + - Bhumika Goyal + - Andy Gross + - Juergen Gross + - Shawn Guo + - Ulf Hansson + - Stephen Hemminger (Microsoft) + - Tejun Heo + - Rob Herring + - Masami Hiramatsu + - Michal Hocko + - Simon Horman + - Johan Hovold (Hovold Consulting AB) + - Christophe JAILLET + - Olof Johansson + - Lee Jones (Linaro) + - Heiner Kallweit + - Srinivas Kandagatla + - Jan Kara + - Shuah Khan (Samsung) + - David Kershner + - Jaegeuk Kim + - Namhyung Kim + - Colin Ian King + - Jeff Kirsher + - Greg Kroah-Hartman (Linux Foundation) + - Christian König + - Vinod Koul + - Krzysztof Kozlowski + - Viresh Kumar + - Aneesh Kumar K.V + - Julia Lawall + - Doug Ledford + - Chuck Lever (Oracle) + - Daniel Lezcano + - Shaohua Li + - Xin Long + - Tony Luck + - Catalin Marinas (Arm Ltd) + - Mike Marshall + - Chris Mason + - Paul E. McKenney + - Arnaldo Carvalho de Melo + - David S. Miller + - Ingo Molnar + - Kuninori Morimoto + - Trond Myklebust + - Martin K. Petersen (Oracle) + - Borislav Petkov + - Jiri Pirko + - Josh Poimboeuf + - Sebastian Reichel (Collabora) + - Guenter Roeck + - Joerg Roedel + - Leon Romanovsky + - Steven Rostedt (VMware) + - Frank Rowand + - Ivan Safonov + - Anna Schumaker + - Jes Sorensen + - K.Y. Srinivasan + - David Sterba (SUSE) + - Heiko Stuebner + - Jiri Kosina (SUSE) + - Willy Tarreau + - Dmitry Torokhov + - Linus Torvalds + - Thierry Reding + - Rik van Riel + - Luis R. Rodriguez + - Geert Uytterhoeven (Glider bvba) + - Eduardo Valentin (Amazon.com) + - Daniel Vetter + - Linus Walleij + - Richard Weinberger + - Dan Williams + - Rafael J. Wysocki + - Arvind Yadav + - Masahiro Yamada + - Wei Yongjun + - Lv Zheng + - Marc Zyngier (Arm Ltd) 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 0000000000..30c272b2a2 --- /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 0000000000..4a92ebb619 --- /dev/null +++ b/Documentation/translations/zh_CN/process/magic-number.rst @@ -0,0 +1,73 @@ +.. _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`` +APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c`` +FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h`` +SLIP_MAGIC 0x5302 slip ``drivers/net/slip.h`` +BAYCOM_MAGIC 0x19730510 baycom_state ``drivers/net/baycom_epp.c`` +HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state ``include/linux/hdlcdrv.h`` +KV_MAGIC 0x5f4b565f kernel_vars_s ``arch/mips/include/asm/sn/klkernvars.h`` +CODA_MAGIC 0xC0DAC0DA coda_file_info ``fs/coda/coda_fs_i.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`` +NMI_MAGIC 0x48414d4d455201 nmi_s ``arch/mips/include/asm/sn/nmi.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 0000000000..8053ae4743 --- /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] 本文件并不是通过回答问题,而是通过让提问者痛苦地明白,我们不知道 + 答案是什么。 + +不管怎样,这里是: + +.. _cn_decisions: + +1)决策 +------- + +每个人都认为管理者做决定,而且决策很重要。决定越大越痛苦,管理者就必须越高级。 +这很明显,但事实并非如此。 + +最重要的是 **避免** 做出决定。尤其是,如果有人告诉你“选择(a)或(b), +我们真的需要你来做决定”,你就是陷入麻烦的管理者。你管理的人比你更了解细节, +所以如果他们来找你做技术决策,你完蛋了。你显然没有能力为他们做这个决定。 + +(推论:如果你管理的人不比你更了解细节,你也会被搞砸,尽管原因完全不同。 +也就是说,你的工作是错的,他们应该管理你的才智) + +所以最重要的是 **避免** 做出决定,至少是那些大而痛苦的决定。做一些小的 +和非结果性的决定是很好的,并且使您看起来好像知道自己在做什么,所以内核管理者 +需要做的是将那些大的和痛苦的决定变成那些没有人真正关心的小事情。 + +这有助于认识到一个大的决定和一个小的决定之间的关键区别是你是否可以在事后修正 +你的决定。任何决定都可以通过始终确保如果你错了(而且你一定会错),你以后总是 +可以通过回溯来弥补损失。突然间,你就要做两个无关紧要的决定,一个是错误的,另 +一个是正确的。 + +人们甚至会认为这是真正的领导能力(咳,胡说,咳)。 + +因此,避免重大决策的关键在于避免做那些无法挽回的事情。不要被引导到一个你无法 +逃离的角落。走投无路的老鼠可能很危险——走投无路的管理者真可怜。 + +事实证明,由于没有人会愚蠢到让内核管理者承担巨大的财政责任,所以通常很容易 +回溯。既然你不可能浪费掉你无法偿还的巨额资金,你唯一可以回溯的就是技术决策, +而回溯很容易:只要告诉大家你是个不称职的傻瓜,说对不起,然后撤销你去年让别 +人所做的毫无价值的工作。突然间,你一年前做的决定不在是一个重大的决定,因为 +它很容易被推翻。 + +事实证明,有些人对接受这种方法有困难,原因有两个: + + - 承认你是个白痴比看起来更难。我们都喜欢保持形象,在公共场合说你错了有时 + 确实很难。 + - 如果有人告诉你,你去年所做的工作终究是不值得的,那么对那些可怜的低级工 + 程师来说也是很困难的,虽然实际的 **工作** 很容易删除,但你可能已经不可 + 挽回地失去了工程师的信任。记住:“不可撤销”是我们一开始就试图避免的, + 而你的决定终究是一个重大的决定。 + +令人欣慰的是,这两个原因都可以通过预先承认你没有任何线索,提前告诉人们你的 +决定完全是初步的,而且可能是错误的事情来有效地缓解。你应该始终保留改变主意 +的权利,并让人们 **意识** 到这一点。当你 **还没有** 做过真正愚蠢的事情的时 +候,承认自己是愚蠢的要容易得多。 + +然后,当它真的被证明是愚蠢的时候,人们就转动他们的眼珠说“哎呀,下次不要了”。 + +这种对不称职的先发制人的承认,也可能使真正做这项工作的人也会三思是否值得做。 +毕竟,如果他们不确定这是否是一个好主意,你肯定不应该通过向他们保证他们所做 +的工作将会进入(内核)鼓励他们。在他们开始一项巨大的努力之前,至少让他们三 +思而后行。 + +记住:他们最好比你更了解细节,而且他们通常认为他们对每件事都有答案。作为一 +个管理者,你能做的最好的事情不是灌输自信,而是对他们所做的事情进行健康的批 +判性思考。 + +顺便说一句,另一种避免做出决定的方法是看起来很可怜的抱怨 “我们不能两者兼 +得吗?” 相信我,它是有效的。如果不清楚哪种方法更好,他们最终会弄清楚的。 +最终的答案可能是两个团队都会因为这种情况而感到沮丧,以至于他们放弃了。 + +这听起来像是一个失败,但这通常是一个迹象,表明两个项目都有问题,而参与其中 +的人不能做决定的原因是他们都是错误的。你最终会闻到玫瑰的味道,你避免了另一 +个你本可以搞砸的决定。 + +2)人 +----- + +大多数人都是白痴,做一名管理者意味着你必须处理好这件事,也许更重要的是, +**他们** 必须处理好你。 + +事实证明,虽然很容易纠正技术错误,但不容易纠正人格障碍。你只能和他们的和 +你的(人格障碍)共处。 + +但是,为了做好作为内核管理者的准备,最好记住不要烧掉任何桥梁,不要轰炸任何 +无辜的村民,也不要疏远太多的内核开发人员。事实证明,疏远人是相当容易的,而 +亲近一个疏远的人是很难的。因此,“疏远”立即属于“不可逆”的范畴,并根据 +:ref:`cn_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 0000000000..fabdc338db --- /dev/null +++ b/Documentation/translations/zh_CN/process/programming-language.rst @@ -0,0 +1,71 @@ +.. 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语言 :ref:`c-language <cn_c-language>` 编写的。更准确地说,内核通常是用 :ref:`gcc <cn_gcc>` +在 ``-std=gnu11`` :ref:`gcc-c-dialect-options <cn_gcc-c-dialect-options>` 下编译的:ISO C11的 GNU 方言 + +这种方言包含对语言 :ref:`gnu-extensions <cn_gnu-extensions>` 的许多扩展,当然,它们许多都在内核中使用。 + +对于一些体系结构,有一些使用 :ref:`clang <cn_clang>` 和 :ref:`icc <cn_icc>` 编译内核 +的支持,尽管在编写此文档时还没有完成,仍需要第三方补丁。 + +属性 +---- + +在整个内核中使用的一个常见扩展是属性(attributes) :ref:`gcc-attribute-syntax <cn_gcc-attribute-syntax>` +属性允许将实现定义的语义引入语言实体(如变量、函数或类型),而无需对语言进行 +重大的语法更改(例如添加新关键字) :ref:`n2049 <cn_n2049>` + +在某些情况下,属性是可选的(即不支持这些属性的编译器仍然应该生成正确的代码, +即使其速度较慢或执行的编译时检查/诊断次数不够) + +内核定义了伪关键字(例如, ``pure`` ),而不是直接使用GNU属性语法(例如, +``__attribute__((__pure__))`` ),以检测可以使用哪些关键字和/或缩短代码, 具体 +请参阅 ``include/linux/compiler_attributes.h`` + +.. _cn_c-language: + +c-language + http://www.open-std.org/jtc1/sc22/wg14/www/standards + +.. _cn_gcc: + +gcc + https://gcc.gnu.org + +.. _cn_clang: + +clang + https://clang.llvm.org + +.. _cn_icc: + +icc + https://software.intel.com/en-us/c-compilers + +.. _cn_gcc-c-dialect-options: + +c-dialect-options + https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html + +.. _cn_gnu-extensions: + +gnu-extensions + https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html + +.. _cn_gcc-attribute-syntax: + +gcc-attribute-syntax + https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html + +.. _cn_n2049: + +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 0000000000..b4ddb6e88d --- /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 0000000000..fba361f2dd --- /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 0000000000..3d6ee21c74 --- /dev/null +++ b/Documentation/translations/zh_CN/process/submit-checklist.rst @@ -0,0 +1,111 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: Documentation/process/submit-checklist.rst +:Translator: + - Alex Shi <alexs@kernel.org> + - Wu XiangCheng <bobwxc@email.cn> + +.. _cn_submitchecklist: + +Linux内核补丁提交检查单 +~~~~~~~~~~~~~~~~~~~~~~~ + +如果开发人员希望看到他们的内核补丁提交更快地被接受,那么他们应该做一些基本 +的事情。 + +这些都是在 Documentation/translations/zh_CN/process/submitting-patches.rst +和其他有关提交Linux内核补丁的文档中提供的。 + +1) 如果使用工具,则包括定义/声明该工具的文件。不要依赖其他头文件来引入您使用 + 的头文件。 + +2) 干净的编译: + + a) 使用合适的 ``CONFIG`` 选项 ``=y``、``=m`` 和 ``=n`` 。没有 ``gcc`` + 警告/错误,没有链接器警告/错误。 + + b) 通过 ``allnoconfig`` 、 ``allmodconfig`` + + c) 使用 ``O=builddir`` 时可以成功编译 + + d) 任何 Doucmentation/ 下的变更都能成功构建且不引入新警告/错误。 + 用 ``make htmldocs`` 或 ``make pdfdocs`` 检验构建情况并修复问题。 + +3) 通过使用本地交叉编译工具或其他一些构建设施在多个CPU体系结构上构建。 + +4) PPC64是一种很好的交叉编译检查体系结构,因为它倾向于对64位的数使用无符号 + 长整型。 + +5) 按 Documentation/translations/zh_CN/process/coding-style.rst 所述检查您的 + 补丁是否为常规样式。在提交之前使用补丁样式检查器 ``scripts/checkpatch.pl`` + 检查是否有轻微的冲突。您应该能够处理您的补丁中存在的所有 + 违规行为。 + +6) 任何新的或修改过的 ``CONFIG`` 选项都不应搞乱配置菜单,并默认为关闭,除非 + 它们符合 ``Documentation/kbuild/kconfig-language.rst`` 菜单属性:默认值中 + 记录的例外条件。 + +7) 所有新的 ``kconfig`` 选项都有帮助文本。 + +8) 已仔细审查了相关的 ``Kconfig`` 组合。这很难用测试来纠正——脑力在这里是有 + 回报的。 + +9) 通过 sparse 清查。 + (参见 Documentation/translations/zh_CN/dev-tools/sparse.rst ) + +10) 使用 ``make checkstack`` 和 ``make namespacecheck`` 并修复他们发现的任何 + 问题。 + + .. note:: + + ``checkstack`` 并不会明确指出问题,但是任何一个在堆栈上使用超过512 + 字节的函数都可以进行更改。 + +11) 包括 :ref:`kernel-doc <kernel_doc_zh>` 内核文档以记录全局内核API。(静态 + 函数不需要,但也可以。)使用 ``make htmldocs`` 或 ``make pdfdocs`` 检查 + :ref:`kernel-doc <kernel_doc_zh>` 并修复任何问题。 + +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`` 和 ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` 。 + +13) 在 ``CONFIG_SMP``, ``CONFIG_PREEMPT`` 开启和关闭的情况下都进行构建和运行 + 时测试。 + +14) 所有代码路径都已在启用所有死锁检测(lockdep)功能的情况下运行。 + +15) 所有新的 ``/proc`` 条目都记录在 ``Documentation/`` + +16) 所有新的内核引导参数都记录在 + Documentation/admin-guide/kernel-parameters.rst 中。 + +17) 所有新的模块参数都记录在 ``MODULE_PARM_DESC()`` + +18) 所有新的用户空间接口都记录在 ``Documentation/ABI/`` 中。有关详细信息, + 请参阅 ``Documentation/ABI/README`` 。更改用户空间接口的补丁应该抄送 + linux-api@vger.kernel.org。 + +19) 已通过至少注入slab和page分配失败进行检查。请参阅 ``Documentation/fault-injection/`` 。 + 如果新代码是实质性的,那么添加子系统特定的故障注入可能是合适的。 + +20) 新添加的代码已经用 ``gcc -W`` 编译(使用 ``make EXTRA-CFLAGS=-W`` )。这 + 将产生大量噪声,但对于查找诸如“警告:有符号和无符号之间的比较”之类的错误 + 很有用。 + +21) 在它被合并到-mm补丁集中之后进行测试,以确保它仍然与所有其他排队的补丁以 + 及VM、VFS和其他子系统中的各种更改一起工作。 + +22) 所有内存屏障(例如 ``barrier()``, ``rmb()``, ``wmb()`` )都需要源代码注 + 释来解释它们正在执行的操作及其原因的逻辑。 + +23) 如果补丁添加了任何ioctl,那么也要更新 + ``Documentation/userspace-api/ioctl/ioctl-number.rst`` 。 + +24) 如果修改后的源代码依赖或使用与以下 ``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-patches.rst b/Documentation/translations/zh_CN/process/submitting-patches.rst new file mode 100644 index 0000000000..f8978f0205 --- /dev/null +++ b/Documentation/translations/zh_CN/process/submitting-patches.rst @@ -0,0 +1,657 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +.. include:: ../disclaimer-zh_CN.rst + +.. _cn_submittingpatches: + +:Original: Documentation/process/submitting-patches.rst + +:译者: + - 钟宇 TripleX Chung <xxx.phy@gmail.com> + - 时奎亮 Alex Shi <alexs@kernel.org> + - 吴想成 Wu XiangCheng <bobwxc@email.cn> + +:校译: + - 李阳 Li Yang <leoyang.li@nxp.com> + - 王聪 Wang Cong <xiyou.wangcong@gmail.com> + + +提交补丁:如何让你的改动进入内核 +================================ + +对于想要将改动提交到 Linux 内核的个人或者公司来说,如果不熟悉“规矩”, +提交的流程会让人畏惧。本文档包含了一系列建议,可以大大提高你 +的改动被接受的机会. + +本文档以较为简洁的行文给出了大量建议。关于内核开发流程如何进行的详细信息, +参见: Documentation/translations/zh_CN/process/development-process.rst 。 +Documentation/translations/zh_CN/process/submit-checklist.rst 给出了一系列 +提交补丁之前要检查的事项。设备树相关的补丁,请参阅 +Documentation/devicetree/bindings/submitting-patches.rst 。 + +本文档假设您正在使用 ``git`` 准备你的补丁。如果您不熟悉 ``git`` ,最好学习 +如何使用它,这将使您作为内核开发人员的生活变得更加轻松。 + +部分子系统和维护人员的树有一些关于其工作流程和要求的额外信息,请参阅 +Documentation/process/maintainer-handbooks.rst 。 + +获取当前源码树 +-------------- + +如果您手头没有当前内核源代码的存储库,请使用 ``git`` 获取一份。您需要先获取 +主线存储库,它可以通过以下命令拉取:: + + git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + +但是,请注意,您可能不想直接针对主线树进行开发。大多数子系统维护人员运 +行自己的树,并希望看到针对这些树准备的补丁。请参见MAINTAINERS文件中子系 +统的 **T:** 项以查找该树,或者直接询问维护者该树是否未在其中列出。 + +.. _zh_describe_changes: + +描述你的改动 +------------ + +描述你的问题。无论您的补丁是一行错误修复还是5000行新功能,都必须有一个潜在 +的问题激励您完成这项工作。说服审阅者相信有一个问题值得解决,让他们读完第一段 +后就能明白这一点。 + +描述用户可见的影响。直接崩溃和锁定是相当有说服力的,但并不是所有的错误都那么 +明目张胆。即使在代码审阅期间发现了这个问题,也要描述一下您认为它可能对用户产 +生的影响。请记住,大多数Linux安装运行的内核来自二级稳定树或特定于供应商/产品 +的树,只从上游精选特定的补丁,因此请包含任何可以帮助您将更改定位到下游的内容: +触发的场景、DMESG的摘录、崩溃描述、性能回归、延迟尖峰、锁定等。 + +质量优化和权衡。如果您声称在性能、内存消耗、堆栈占用空间或二进制大小方面有所 +改进,请包括支持它们的数据。但也要描述不明显的成本。优化通常不是零成本的,而是 +在CPU、内存和可读性之间进行权衡;或者,做探索性的工作,在不同的工作负载之间进 +行权衡。请描述优化的预期缺点,以便审阅者可以权衡成本和收益。 + +提出问题之后,就要详细地描述一下您实际在做的技术细节。对于审阅者来说,用简练的 +英语描述代码的变化是很重要的,以验证代码的行为是否符合您的意图。 + +如果您将补丁描述写成“标准格式”,可以很容易地作为“提交日志”放入Linux的源代 +码管理系统 ``git`` 中,那么维护人员将非常感谢您。 +参见 :ref:`zh_the_canonical_patch_format` 。 + +每个补丁只解决一个问题。如果你的描述开始变长,这就表明你可能需要拆分你的补丁。 +请见 :ref:`zh_split_changes` 。 + +提交或重新提交补丁或补丁系列时,请包括完整的补丁说明和理由。不要 +只说这是补丁(系列)的第几版。不要期望子系统维护人员引用更早的补丁版本或引用 +URL来查找补丁描述并将其放入补丁中。也就是说,补丁(系列)及其描述应该是独立的。 +这对维护人员和审阅者都有好处。一些审阅者可能甚至没有收到补丁的早期版本。 + +用祈使句描述你的变更,例如“make xyzzy do frotz”而不是“[This patch]make +xyzzy do frotz”或“[I]changed xyzzy to do frotz”,就好像你在命令代码库改变 +它的行为一样。 + +如果您想要引用一个特定的提交,不要只引用提交的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发生冲突,这种情况 +也可能在五年后改变。 + +如果该变更的相关讨论或背景信息可以在网上查阅,请加上“Link:”标签指向它。例如 +你的补丁修复了一个缺陷,需要添加一个带有URL的标签指向邮件列表存档或缺陷跟踪器 +的相关报告;如果该补丁是由一些早先邮件列表讨论或网络上的记录引起的,请指向它。 + +当链接到邮件列表存档时,请首选lore.kernel.org邮件存档服务。用邮件中的 +``Message-ID`` 头(去掉尖括号)可以创建链接URL。例如:: + + Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/ + +请检查该链接以确保可用且指向正确的邮件。 + +不过,在没有外部资源的情况下,也要尽量让你的解释可理解。除了提供邮件列表存档或 +缺陷的URL之外,还要需要总结该补丁的相关讨论要点。 + +如果补丁修复了特定提交中的错误,例如使用 ``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\") + +使用示例:: + + $ git log -1 --pretty=fixes 54a4f0239f2e + Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed") + +.. _zh_split_changes: + +拆分你的改动 +------------ + +将每个 **逻辑更改** 拆分成一个单独的补丁。 + +例如,如果你的改动里同时有bug修正和性能优化,那么把这些改动拆分到两个或 +者更多的补丁文件中。如果你的改动包含对API的修改,并且增加了一个使用该新API +的驱动,那么把这些修改分成两个补丁。 + +另一方面,如果你将一个单独的改动做成多个补丁文件,那么将它们合并成一个 +单独的补丁文件。这样一个逻辑上单独的改动只被包含在一个补丁文件里。 + +需要记住的一点是,每个补丁的更改都应易于理解,以便审阅者验证。每个补丁都应该 +对其价值进行阐述。 + +如果有一个补丁依赖另外一个补丁来完成它的改动,那没问题。直接在你的补 +丁描述里指出 **“这个补丁依赖某补丁”** 就好了。 + +在将您的更改划分为一系列补丁时,要特别注意确保内核在应用系列中的每个补丁之后 +都能正常构建和运行。使用 ``git bisect`` 来追踪问题的开发者可能会在任何地方分 +割你的补丁系列;如果你在中间引入错误,他们不会感谢你。 + +如果你不能将补丁系列浓缩得更小,那么每次大约发送出15个补丁,然后等待审阅 +和集成。 + +检查你的更改风格 +---------------- + +检查您的补丁是否违反了基本样式规定,详细信息参见 +Documentation/translations/zh_CN/process/coding-style.rst +中找到。如果不这样做,只会浪费审阅者的时间,并且会导致你的补丁被拒绝,甚至 +可能没有被阅读。 + +一个重要的例外是在将代码从一个文件移动到另一个文件时——在这种情况下,您不应 +该在移动代码的同一个补丁中修改移动的代码。这清楚地描述了移动代码和您的更改 +的行为。这大大有助于审阅实际差异,并允许工具更好地跟踪代码本身的历史。 + +在提交之前,使用补丁样式检查程序检查补丁(scripts/check patch.pl)。不过, +请注意,样式检查程序应该被视为一个指南,而不是作为人类判断的替代品。如果您 +的代码看起来更好,但有违规行为,那么最好别管它。 + +检查者报告三个级别: + + - ERROR:很可能出错的事情 + - WARNING:需要仔细审阅的事项 + - CHECK:需要思考的事情 + +您应该能够判断您的补丁中存在的所有违规行为。 + +选择补丁收件人 +-------------- + +您应该总是知会任何补丁相应代码的子系统维护人员;查看 +维护人员文件和源代码修订历史记录,以了解这些维护人员是谁。脚本 +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 内核的最终裁决者。他的邮件地址是 +torvalds@linux-foundation.org 。他收到的邮件很多,所以一般来说最好 **别** +给他发邮件。 + +如果您有修复可利用安全漏洞的补丁,请将该补丁发送到 security@kernel.org 。对于 +严重的bug,可以考虑短期禁令以允许分销商(有时间)向用户发布补丁;在这种情况下, +显然不应将补丁发送到任何公共列表。 +参见 Documentation/translations/zh_CN/admin-guide/security-bugs.rst 。 + +修复已发布内核中严重错误的补丁程序应该抄送给稳定版维护人员,方法是把以下列行 +放进补丁的签准区(注意,不是电子邮件收件人):: + + Cc: stable@vger.kernel.org + +除了本文件之外,您还应该阅读 +Documentation/translations/zh_CN/process/stable-kernel-rules.rst 。 + +如果更改影响到用户侧内核接口,请向手册页维护人员(如维护人员文件中所列)发送 +手册页补丁,或至少发送更改通知,以便一些信息进入手册页。还应将用户空间API +更改抄送到 linux-api@vger.kernel.org 。 + + +不要MIME编码,不要链接,不要压缩,不要附件,只要纯文本 +------------------------------------------------------ + +Linus 和其他的内核开发者需要阅读和评论你提交的改动。对于内核开发者来说 +,可以“引用”你的改动很重要,使用一般的邮件工具,他们就可以在你的 +代码的任何位置添加评论。 + +因为这个原因,所有的提交的补丁都是邮件中“内嵌”的。最简单(和推荐)的方法就 +是使用 ``git send-email`` 。https://git-send-email.io 有 ``git send-email`` +的交互式教程。 + +如果你选择不用 ``git send-email`` : + +.. warning:: + + 如果你使用剪切-粘贴你的补丁,小心你的编辑器的自动换行功能破坏你的补丁 + +不要将补丁作为MIME编码的附件,不管是否压缩。很多流行的邮件软件不 +是任何时候都将MIME编码的附件当作纯文本发送的,这会使得别人无法在你的 +代码中加评论。另外,MIME编码的附件会让Linus多花一点时间来处理,这就 +降低了你的改动被接受的可能性。 + +例外:如果你的邮路损坏了补丁,那么有人可能会要求你使用MIME重新发送补丁。 + +请参阅 Documentation/translations/zh_CN/process/email-clients.rst +以获取有关配置电子邮件客户端以使其不受影响地发送补丁的提示。 + +回复审阅意见 +------------ + +你的补丁几乎肯定会得到审阅者对补丁改进方法的评论(以回复邮件的形式)。您必须 +对这些评论作出回应;让补丁被忽略的一个好办法就是忽略审阅者的意见。直接回复邮 +件来回应意见即可。不会导致代码更改的意见或问题几乎肯定会带来注释或变更日志的 +改变,以便下一个审阅者更好地了解正在发生的事情。 + +一定要告诉审阅者你在做什么改变,并感谢他们的时间。代码审阅是一个累人且耗时的 +过程,审阅者有时会变得暴躁。即使在这种情况下,也要礼貌地回应并解决他们指出的 +问题。当发送下一版时,在封面邮件或独立补丁里加上 ``patch changelog`` 说明与 +前一版本的不同之处(参见 :ref:`zh_the_canonical_patch_format` )。 + +.. _zh_resend_reminders: + +不要泄气或不耐烦 +---------------- + +提交更改后,请耐心等待。审阅者是大忙人,可能无法立即审阅您的补丁。 + +曾几何时,补丁曾在没收到评论的情况下消失在虚空中,但现在开发过程应该更加顺利了。 +您应该在一周左右的时间内收到评论;如果没有收到评论,请确保您已将补丁发送 +到正确的位置。在重新提交或联系审阅者之前至少等待一周——在诸如合并窗口之类的 +繁忙时间可能更长。 + +在等了几个星期后,用带RESEND的主题重发补丁也是可以的:: + + [PATCH Vx RESEND] sub/sys: Condensed patch summary + +当你发布补丁(系列)修改版的时候,不要加上“RESEND”——“RESEND”只适用于重 +新提交之前未经修改的补丁(系列)。 + +主题中包含 PATCH +---------------- + +由于到Linus和linux-kernel的电子邮件流量很高,通常会在主题行前面加上[PATCH] +前缀。这使Linus和其他内核开发人员更容易将补丁与其他电子邮件讨论区分开。 + +``git send-email`` 会自动为你加上。 + +签署你的作品——开发者来源认证 +------------------------------ + +为了加强对谁做了何事的追踪,尤其是对那些透过好几层维护者才最终到达的补丁,我 +们在通过邮件发送的补丁上引入了“签署(sign-off)”流程。 + +“签署”是在补丁注释最后的一行简单文字,认证你编写了它或者其他 +人有权力将它作为开放源代码的补丁传递。规则很简单:如果你能认证如下信息: + +开发者来源认证 1.1 +^^^^^^^^^^^^^^^^^^ + +对于本项目的贡献,我认证如下信息: + + (a) 这些贡献是完全或者部分的由我创建,我有权利以文件中指出 + 的开放源代码许可证提交它;或者 + + (b) 这些贡献基于以前的工作,据我所知,这些以前的工作受恰当的开放 + 源代码许可证保护,而且,根据文件中指出的许可证,我有权提交修改后的贡献, + 无论是完全还是部分由我创造,这些贡献都使用同一个开放源代码许可证 + (除非我被允许用其它的许可证);或者 + + (c) 这些贡献由认证(a),(b)或者(c)的人直接提供给我,而 + 且我没有修改它。 + + (d) 我理解并同意这个项目和贡献是公开的,贡献的记录(包括我 + 一起提交的个人记录,包括sign-off)被永久维护并且可以和这个项目 + 或者开放源代码的许可证同步地再发行。 + +那么加入这样一行:: + + Signed-off-by: Random J Developer <random@developer.example.org> + +使用你的真名(抱歉,不能使用假名或者匿名。)如果使用 ``git commit -s`` 的话 +将会自动完成。撤销也应当包含“Signed-off-by”, ``git revert -s`` 会帮你搞定。 + +有些人会在最后加上额外的标签。现在这些东西会被忽略,但是你可以这样做,来标记 +公司内部的过程,或者只是指出关于签署的一些特殊细节。 + +作者签署之后的任何其他签署(Signed-off-by:'s)均来自处理和传递补丁的人员,但 +未参与其开发。签署链应当反映补丁传播到维护者并最终传播到Linus所经过的 **真实** +路径,首个签署指明单个作者的主要作者身份。 + +何时使用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:不一定表示对整个补丁的确认。例如,如果一个补丁影响多个子系统,并且 +有一个来自某个子系统维护者的Acked-By:,那么这通常表示只确认影响维护者代码的部 +分。这里应该仔细判断。如有疑问,应参考邮件列表存档中的原始讨论。 + +如果某人本应有机会对补丁进行评论,但没有提供此类评论,您可以选择在补丁中添加 +``Cc:`` 这是唯一可以在没有被该人明确同意的情况下添加的标签——但它应该表明 +这个人是在补丁上抄送的。此标签记录了讨论中包含的潜在利益相关方。 + +Co-developed-by: 声明补丁是由多个开发人员共同创建的;当几个人在一个补丁上工 +作时,它用于给出共同作者(除了From:所给出的作者之外)。因为Co-developed-by: +表示作者身份,所以每个Co-developed-by:必须紧跟在相关合作作者的签署之后。标准 +签署程序要求Singed-off-by:标签的顺序应尽可能反映补丁的时间历史,无论作者是通 +过From:还是Co-developed-by:表明。值得注意的是,最后一个Singed-off-by:必须是 +提交补丁的开发人员。 + +注意,如果From:作者也是电子邮件标题的From:行中列出的人,则From:标签是可选的。 + +被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> + + +使用Reported-by:、Tested-by:、Reviewed-by:、Suggested-by:和Fixes: +----------------------------------------------------------------- + +Reported-by: 给那些发现错误并报告错误的人致谢,它希望激励他们在将来再次帮助 +我们。请注意,如果bug是以私有方式报告的,那么在使用Reported-by标签之前,请 +先请求许可。此标签是为Bug设计的;请不要将其用于感谢功能请求。 + +Tested-by: 标签表示补丁已由指定的人(在某些环境中)成功测试。这个标签通知 +维护人员已经执行了一些测试,为将来的补丁提供了一种定位测试人员的方法,并彰显测试人员的功劳。 + +Reviewed-by:根据审阅者的监督声明,表明该补丁已被审阅并被认为是可接受的: + + +审阅者的监督声明 +^^^^^^^^^^^^^^^^ + +通过提供我的Reviewed-by:标签,我声明: + + (a) 我已经对这个补丁进行了一次技术审阅,以评估它是否适合被包含到 + 主线内核中。 + + (b) 与补丁相关的任何问题、顾虑或问题都已反馈给提交者。我对提交者对 + 我的评论的回应感到满意。 + + (c) 虽然这一提交可能仍可被改进,但我相信,此时,(1)对内核 + 进行了有价值的修改,(2)没有包含争论中涉及的已知问题。 + + (d) 虽然我已经审阅了补丁并认为它是健全的,但我不会(除非另有明确 + 说明)作出任何保证或担保它会在任何给定情况下实现其规定的目的 + 或正常运行。 + +Reviewed-by是一种观点声明,即补丁是对内核的适当修改,没有任何遗留的严重技术 +问题。任何感兴趣的审阅者(完成工作的人)都可以为一个补丁提供一个Reviewed-by +标签。此标签用于向审阅者提供致谢,并通知维护者补丁的审阅进度。 +当Reviewed-by:标签由已知了解主题区域并执行彻底检查的审阅者提供时,通常会增加 +补丁进入内核的可能性。 + +一旦从测试人员或审阅者的“Tested-by”和“Reviewed-by”标签出现在邮件列表中, +作者应在发送下一个版本时将其添加到适用的补丁中。但是,如果补丁在以下版本中发 +生了实质性更改,这些标签可能不再适用,因此应该删除。通常,在补丁更改日志中 +(在 ``---`` 分隔符之后)应该提到删除某人的测试者或审阅者标签。 + +Suggested-by: 表示补丁的想法是由指定的人提出的,并确保将此想法归功于指定的 +人。请注意,未经许可,不得添加此标签,特别是如果该想法未在公共论坛上发布。 +也就是说,如果我们勤快地致谢创意提供者,他们将受到鼓舞,很有希望在未来再次 +帮助我们。 + +Fixes: 指示补丁修复了之前提交的一个问题。它可以便于确定错误的来源,这有助于 +检查错误修复。这个标签还帮助稳定内核团队确定应该接收修复的稳定内核版本。这是 +指示补丁修复的错误的首选方法。请参阅 :ref:`zh_describe_changes` 了解更多信息。 + +.. note:: + + 附加Fixes:标签不会改变稳定内核规则流程,也不改变所有稳定版补丁抄送 + stable@vger.kernel.org的要求。有关更多信息,请阅读 + Documentation/translations/zh_CN/process/stable-kernel-rules.rst 。 + +.. _zh_the_canonical_patch_format: + +标准补丁格式 +------------ + +本节描述如何格式化补丁本身。请注意,如果您的补丁存储在 ``Git`` 存储库中,则 +可以使用 ``git format-patch`` 进行正确的补丁格式化。但是,这些工具无法创建 +必要的文本,因此请务必阅读下面的说明。 + +标准的补丁标题行是:: + + Subject: [PATCH 001/123] 子系统:一句话概述 + +标准补丁的信体包含如下部分: + + - 一个 ``from`` 行指出补丁作者。后跟空行(仅当发送补丁的人不是作者时才需要)。 + + - 说明文字,每行最长75列,这将被复制到永久变更日志来描述这个补丁。 + + - 一个空行 + + - 上述的 ``Signed-off-by:`` 行,也将出现在更改日志中。 + + - 只包含 ``---`` 的标记线。 + + - 任何其他不适合放在变更日志的注释。 + + - 实际补丁( ``diff`` 输出)。 + +标题行的格式,使得对标题行按字母序排序非常的容易——很多邮件客户端都 +可以支持——因为序列号是用零填充的,所以按数字排序和按字母排序是一样的。 + +邮件标题中的“子系统”标识哪个内核子系统将被打补丁。 + +邮件标题中的“一句话概述”扼要的描述邮件中的补丁。“一句话概述” +不应该是一个文件名。对于一个补丁系列(“补丁系列”指一系列的多个相关补 +丁),不要对每个补丁都使用同样的“一句话概述”。 + +记住邮件的“一句话概述”会成为该补丁的全局唯一标识。它会进入 ``git`` +的改动记录里。然后“一句话概述”会被用在开发者的讨论里,用来指代这个补 +丁。用户将希望通过搜索引擎搜索“一句话概述”来找到那些讨论这个补丁的文 +章。当人们在两三个月后使用诸如 ``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列的宽度,也许会有一些缩进。) +( ``git`` 默认会生成合适的diffstat。) + +其余那些只适用于当时或者与维护者相关的注解,不合适放到永久的改动日志里的,也 +应该放这里。较好的例子就是 ``补丁更改记录`` ,记录了v1和v2版本补丁之间的差异。 + +请将此信息放在将变更日志与补丁的其余部分分隔开的 ``---`` 行 **之后** 。版本 +信息不是提交到git树的变更日志的一部分。只是供审阅人员使用的附加信息。如果将 +其放置在提交标记上方,则需要手动交互才能将其删除。如果它位于分隔线以下,则在 +应用补丁时会自动剥离:: + + <commit message> + ... + Signed-off-by: Author <author@mail> + --- + V2 -> V3: Removed redundant helper function + V1 -> V2: Cleaned up coding style and addressed review comments + + path/to/file | 5+++-- + ... + +在后面的参考资料中能看到正确补丁格式的更多细节。 + +.. _zh_backtraces: + +提交消息中的回溯(Backtraces) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +回溯有助于记录导致问题的调用链。然而,并非所有回溯都有帮助。例如,早期引导调 +用链是独特而明显的。而逐字复制完整的dmesg输出则会增加时间戳、模块列表、寄存 +器和堆栈转储等分散注意力的信息。 + +因此,最有用的回溯应该从转储中提取相关信息,以更容易集中在真实问题上。下面是 +一个剪裁良好的回溯示例:: + + unchecked MSR access error: WRMSR to 0xd51 (tried to write 0x0000000000000064) + at rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20) + Call Trace: + mba_wrmsr + update_domains + rdtgroup_mkdir + +.. _zh_explicit_in_reply_to: + +明确回复邮件头(In-Reply-To) +----------------------------- + +手动添加回复补丁的的邮件头(In-Reply_To:)是有用的(例如,使用 ``git send-email`` ), +可以将补丁与以前的相关讨论关联起来,例如,将bug补丁链接到电子邮件和bug报告。 +但是,对于多补丁系列,最好避免在回复时使用链接到该系列的旧版本。这样, +补丁的多个版本就不会成为电子邮件客户端中无法管理的引用树。如果链接有用, +可以使用 https://lore.kernel.org/ 重定向器(例如,在封面电子邮件文本中) +链接到补丁系列的早期版本。 + +给出基础树信息 +-------------- + +当其他开发人员收到您的补丁并开始审阅时,知道应该将您的工作放到代码树历史记录 +中的什么位置通常很有用。这对于自动化持续集成流水(CI)特别有用,这些流水线试 +图运行一系列测试,以便在维护人员开始审阅之前确定提交的质量。 + +如果您使用 ``git format-patch`` 生成补丁,则可以通过 ``--base`` 标志在提交中 +自动包含基础树信息。使用此选项最简单、最方便的方法是配合主题分支:: + + $ git checkout -t -b my-topical-branch master + Branch 'my-topical-branch' set up to track local branch 'master'. + Switched to a new branch 'my-topical-branch' + + [perform your edits and commits] + + $ git format-patch --base=auto --cover-letter -o outgoing/ master + outgoing/0000-cover-letter.patch + outgoing/0001-First-Commit.patch + outgoing/... + +当你编辑 ``outgoing/0000-cover-letter.patch`` 时,您会注意到在它的最底部有一 +行 ``base-commit:`` 尾注,它为审阅者和CI工具提供了足够的信息以正确执行 +``git am`` 而不必担心冲突:: + + $ git checkout -b patch-review [base-commit-id] + Switched to a new branch 'patch-review' + $ git am patches.mbox + Applying: First Commit + Applying: ... + +有关此选项的更多信息,请参阅 ``man git-format-patch`` 。 + +.. note:: + + ``--base`` 功能是在2.9.0版git中引入的。 + +如果您不使用git格式化补丁,仍然可以包含相同的 ``base-commit`` 尾注,以指示您 +的工作所基于的树的提交哈希。你应该在封面邮件或系列的第一个补丁中添加它,它应 +该放在 ``---`` 行的下面或所有其他内容之后,即只在你的电子邮件签名之前。 + +参考文献 +-------- + +Andrew Morton,“完美的补丁”(tpp) + <https://www.ozlabs.org/~akpm/stuff/tpp.txt> + +Jeff Garzik,“Linux内核补丁提交格式” + <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html> + +Greg Kroah-Hartman,“如何惹恼内核子系统维护人员” + <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> + +不!!!别再发巨型补丁炸弹给linux-kernel@vger.kernel.org的人们了! + <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net> + +内核 Documentation/translations/zh_CN/process/coding-style.rst + +Linus Torvalds关于标准补丁格式的邮件 + <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org> + +Andi Kleen,“提交补丁之路” + 一些帮助合入困难或有争议的变更的策略。 + + 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 0000000000..ded3b5d0c9 --- /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] https://lwn.net/Articles/233481/ +[2] https://lwn.net/Articles/233482/ + +致谢 +---- + +最初由Randy Dunlap推动并作初步研究 +由Jonathan Corbet撰写 +参考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila, +H. Peter Anvin,Philipp Hahn和Stefan Richter的意见改善了本档。 |