Kernel 开发过程指南

by Jonathan Corbet, corbet@lwn.net

翻译进行中, 可能存在一些错误,会不断地修正中。。。。
    这个 文档的目的 是帮助 开发人员(包括 经理),使其在开发社区 的开发 工作 阻碍降到 最低水平。本文试图写出社区是如何运作,这可以让那些并不非常熟悉Linux内核(或其它自由软件的开发)开发的人员可以进入访问。 虽然这里 有一些 技术材料 ,这 不能不说是一个面向过程 的讨论, 并不需要 深入了解 内核编程 理解。

 

 

1.1:执行摘要

本节的其余部分涵盖了内核开发过程的范围和开发人员和他们的雇主有可能遇到各种障碍。为什么内核代码应合并到官方的(“主线”)的内核,这受到很多因素的影响,包括自动提供给用户,多种形式的社区支持,影响的内核的发展方向的能力。代码贡献给Linux内核必须根据一个GPL兼容的许可。

2节介绍了开发过程,内核的发布周期和合并窗口的机制。 各个阶段包括补丁的开发,代码审查,合并周期。有一些工具和邮件列表的讨论。开发人员希望开始内核开发,建议以跟踪和修复bug作为初步练习。

3节涵盖早期阶段的项目规划,作为重点尽快加入开发社区。

4是关于编码过程,讨论其他开发人员遇到的几个误区。 有些要求是补丁覆盖,有一些工具介绍,可以帮助确保该内核补丁被纠正。

5探讨发布补丁程序用于审查的过程。 补丁必须正确格式和描述,并必须被发送到正确的地方,开发社区非常重视这些问题。 按照本节的建议将有助于确保您的工作达到最佳接收效果。

6节阐述了补丁发布后的一些事宜,工作还远远不会在补丁发布这一点上进行。 与评审人员合作是一个开发过程中的重要组成部分,这部分提供了一个小窍门,以避免在这个重要阶段会发生的一些问题。 假设补丁程序合并到主时线时,工作完成,开发人员将被提醒。

7节介绍了两个“高级”的主题:使用Git管理修补程序和审查他人发布的补丁。

8节是本文的结尾,给出了更多关于内核开发的信息链接。


1.2
:内容概要

Linux内核超过600万行代码,远远超过1000积极的贡献者,是全球最大和最活跃的自由软件中存在的项目之一。 自1991年摸索与发展,这个内核已经发展成为一个最佳级别的操作系统组件,可以运行在袖珍数字音乐播放器,台式电脑,目前存在的最大的超级计算机,以及在所有类型的系统之间运行。 这是一个几乎任何情况稳健,高效,可伸缩的解决方案。

 

随着Linux的增长,希望参与开发的开发人员(或公司)的数量开始增加。 硬件供应商要确保Linux很好地支持他们的产品,使这些产品吸引Linux用户。 嵌入式系统供应商使用Linux作为一个集成的产品组件,需要Linux视为有能力,尽可能地被认为非常适合手头的工作。 基于Linux的产品的分销商和其他软件供应商,Linux明确的兴趣,在于Linux内核功能,性能,和可靠性。 最终用户,也往往会希望改变Linux,使其更好地满足他们的需要。

 

linux最引人注目的特点之一是,,具有必要技能的任何人,都可以它可以访问这些开发者和提高Linux和影响其发展的方向。 专有产品不能提供这种类型的开放,这是一个自由软件过程的特点。 但是,如果有的话,内核甚至比大多数其他自由软件项目开放,一个典型的三个月的内核开发周期可能会涉及1000多个开发人员超过100种不同的公司共同工作(或根本没有一家公司)。

 

与内核开发社区工作并不是特别困难。 但是,尽管如此,许多潜在的贡献者在尝试做内核的工作时已经遇到了困难。 在这里,每天成千上万行的代码被改变,内核社区已经有了自己的与众不同的运营方式,保证它的功能运行顺畅(并生产高品质的产品)。 因此,Linux内核的开发过程与专有的开发方法有很大的不同,这并不奇怪。

 

内核的发展过程,对于新开发者,可能感觉陌生和害怕,但在这背后,有很好的理论基础和丰富经验。 不明白内核社区的方式(或者更糟,试图无视或绕过它们)的开发人员将在这里经历令人沮丧的过程。 开发社区,正在帮助那些正在努力学习的开发人员,没有时间照顾那些不听或不关心开发过程的开发人员。

 

希望看过这份文件,能够避免这种令人沮丧的经历。 在这里有大量的材料,认真阅读它将在短期内给您以回报。 开发社区始终是需要开发者的帮助,有助于使内核变得更好;下面的文字应该帮助你-或那些为你工作的人– 加入我们的社区。

 

1.3:荣誉

这份文档是由乔纳森.科比特(JonathanCorbet)书写的, corbet@lwn.net 。 并从(JamesBerry, Alex Chiang, Roland Dreier, Randy Dunlap, Jake Edge, JiriKosina, Matt Mackall, Amanda McPherson, Andrew Morton, and JochenVoß)得到了改进意见。

这项工作由Linux基金会支持,尤其感谢阿曼达.麦克弗森(AmandaMcPhers),看到这种努力的价值并努力推动它。

 

1.4:提交代码进入主线的重要问题

一些公司和开发商有时想知道为什么他们要费心学习如何与内核社区工作,提交他们的代码进入主线内核(以下简称“主线”是由LinusTorvalds维护的内核并作为Linux发行商的一个基础)。 从短期来看,贡献代码可以看起来像一个可以避免的费用,它似乎更容易保持公正独立的代码和直接支持用户。 事情的真相是,保持代码分离(“脱离源码树(“outof tree”))是一个虚假的经济。

这里有一个内核的发展过程中的一些相关问题,用以说明“脱离源码树”(“outof tree”)的代码成本问题;其中大部分将在更详细地讨论本文档后面。 如下:

  • 已被纳入主流内核合并的代码是提供给所有Linux用户。 它会自动存在于所有可行的发行领域。 无需驱动磁盘,无需下载,无需支持多个版本的多种发行的麻烦;这一切只是为开发商和用户工作。 合并入主线解决了大量发行和技术支持的问题。

  • 虽然内核开发努力保持一个稳定的接口到用户空间,内部的内核API是在不断变化。 一个稳定的内部接口缺乏是一个经过深思熟虑的设计决定;它允许在任何时间根本的改善,从而获得更高质量的代码。 但是,这一政策的结果之一是,任何“脱离源码树”(“outof tree”)代码需要不断维护,如果它要与新的内核一起运行。 维护“脱离源码树”(“outof tree”)代码需要大量的工作。

  • 主线中的代码,相反,不需要这些工作,仅因为这样一个简单的的规则--需要开发者修复所有因API改变造成崩溃的代码。所以代码合并到主线,可以大大降低维护成本。

  • 除此之外,内核中代码,往往会被其它开发者改善。 令人惊讶的结果可能来自授权用户社区和客户提高您的产品。

  • 内核代码受到审查,包括合并到主线之前和之后。 无论多么强大的原始开发者的技能,都会在审查过程中被发现该代码可以改善的方法。 对于在一个封闭的环境下开发的代码,经常检讨发现严重缺陷和安全问题,这毫不虚假。这样的代码很大程度上从外部开发者审查获益。 “脱离源码树”(“outof tree”)代码是低质量的代码。

  • 在开发过程中的参与,是用自己的方式影响内核的发展方向。 用户在一旁听到的抱怨,但积极开发有较强的声音-和执行改变的能力,使内核的工作更好地满足他们的需要。

  • 当代码被单独维护时,第三方提供一个类似的功能的不同的实现的可能性始终存在。 如果这种情况发生,让你的代码合并将更难,甚至不可能合并。 那么你将面临着不愉快的替代品,或(1)无限期保持非标准特性-(”outof tree”)脱离源码树,或(2)放弃你的代码和让您的用户迁移到源码树(“in-tree”)的版本

  • 贡献代码是使得整个进程的工作的根本行动。 通过贡献你的代码,你可以添加新的功能至内核,并提供核心功能和使用的例子给其他内核开发者。 如果你已经制定了Linux代码(或正在考虑这样做),你显然对这个平台继续取得成功很有兴趣,贡献代码是最好帮助确保成功的方法之一。

 

以上所有的推理适用于任何内核代码树外的代码,包括仅以二进制分发的专有代码。 然而,在考虑任何仅提供二进制内核代码发布之前,一些额外的因素应该考虑。 这些因素包括:

  • 围绕专有内核模块分布的法律问题最好模糊一些;相当多的内核的版权持有人认为,大多数只导出二进制模块的内核产品,它们的发布是侵犯GNU通用公共许可证(下文会详细地说)。 作者本人是不是律师,并在此文件的内容都不可能被认为是法律意见。 真正的闭源模块的法律地位只能由法庭来决定。 但是,困扰着这些模块的不明朗因素与此无关。

  • 二进制模块大大提高了调试内核问题的难度,对于这一点,大多数开发者甚至不尝试。 因此,只有二进制模块发布将让您的用户更难获得社区的支持。

  • 只有二进制模块的发布也更难以提供支持,其必须提供发布每个模块版本和每一个内核版本的支持, 大量的单个模块构建可能被要求提供合理全面覆盖的支持,您的用户必须每次分开升级你的模块和升级其内核。

  • 上面所说的一切有关代码审查,对于闭源代码,其问题将成倍增加。 由于这些代码无法获取,它不能被开发社区审查,无疑是会有严重问题。

嵌入式系统制造商,特别是可能受到诱惑,根本不顾以上所说的这个的信念,他们一个自有产品正在出货,它使用一个冻结的内核版本,并要求其发布后不需要更多的开发。 这种说法忽略了普遍的代码审查的价值和让你的用户添加功能到你的产品的价值。 但这些产品中,也有一个有限的商业生活空间,之后,一个新的版本必须被发布。 在这一点上,商家的代码是在主线,良好的维护将会有更好的定位以为获得新的产品市场做好了准备迅速。

 

1.5:许可证

贡献给Linux内核代码需要一些授权许可,但所有的代码必须与2.0版本的GNU通用公共许可证(GPL第二版)兼容,这个许可证覆盖整个内核。 实际上,这意味着所有的代码贡献均按GPLv2(或,语言允许的更高版本的GPL)或三条款BSD许可证授权。 任何没有通过兼容的许可证所涵盖的贡献将不会被接纳进内核。

代码贡献给内核版权作业是不必要的(或被要求)的。 合并进入主线内核所有代码其原有的所有权仍保留,这样一来,内核现在有成千上万的主人。

 

这种所有权结构的一个含义是,任何试图改变内核许可证几乎可以肯定是注定要失败的。 这有几个事态发生,要么所有版权持有人同意授权使用(或他们的代码从内核中移除)。 因此,根本没有前景被迁移到可预见的未来的GPL3版本

 

所有贡献给内核的代码是合法的自由软件,这一些是必须的。 出于这个原因,从匿名(或假名)贡献者的代码将不会被接受。所有参与者都必须对他们的代码“签字”,说明该代码可以在GPL下与内核发布。 代码还没有被授权作为其所有者的自由软件,或可能对内核制造与著作权有关的问题的(如代码是从逆向工程缺乏适当的保障措施努力派生的),不能在内核发布。

 

有关版权事宜的问题在Linux开发邮件列表里很普遍。 这些问题通常会得到不少回答,可是每个人都应该牢记,回答这些问题的人不是律师,不能提供法律意见。 如果你有Linux的源代码有关的法律问题,与懂得这个领域的律师讨论,这是什么也替代不了的。 依赖技术邮件列表得到答案是件危险的事。

 

 

 

2:开发过程的工作机制

 

 

Linux90年代初的内核的开发是一个非常松散的事件,所涉及的用户和开发人员相对较少。 随着数以百万计的用户群,拥有2000名以上的开发者一年的参与开发,内核开发因此发展成为多个开发进程,保证开发的顺利进行。 这个运作的过程需要深入了解,以便成为它的一个有效组成部分。

2.1:蓝图

内核开发人员使用一个松散的基于时间的发布过程,新的重大的内核每两,三个月发布一次。 最近发布的历史是这样的:

2.6.26

2008713

2.6.25

2008416

2.6.24

2008124

2.6.23

07109

2.6.22

200778

2.6.21

07425

2.6.20

200727

 

每一个的2.6.x版本发布都有新的特点,如内部API的变化等。 一个典型的2.6版本可以包含超过10,000变更集,这些变更集包括几十万行代码的变化。 因此,2.6Linux内核开发的领先优势;内核采用了滚动式的发展模式,不断整合重大变化。

 

一个相对简单的工作程序是关于每个版本的补丁合并。 在每个开发周期的开始,也就是“合并窗口”打开。 当时,代码被认为是足够稳定(这是由开发社区接受)被合并到主线内核。 新的开发周期的大量变化(所有的主要改变)这时将要合并,大约每天天1000个改变(“补丁”,或“变化集”)的速度。

 

(顺便说一句,值得注意的是,在综合窗口合并所做的更改不会凭空出来,他们已经提前收集,测试,现场演示。怎样的过程将于稍后详细介绍。)。

 

合并窗口为期两个星期。 在这段时间结束时,LinusTorvalds的将宣布关闭该窗口并发布第一个“rc”内核。 这里比如内核是2.6.26,在合并窗口最后期发布的将会被称为2.6.26-rc1的。 -rc版本是合并新功能结束的信号,并说明下一个稳定内核已经开始。

 

在接下来的六到十个星期,只有解决问题的补丁应提交主线。 有时一个重大的变化是可以允许的,但这样的情况是罕见的;开发者尝试合并新功能至合并窗口往往会得到不友善的接待。 

 

作为一般规则,如果你一个给定的功能错过了合并窗口,最好的办法就是等待下一个开发周期。 (偶尔的例外是用于支持以前不支持的硬件驱动程序,如果他们接触的是非内核源码树(in-tree)代码,他们不可以导致版本回退,并应随时安全添加)。

 

由于主线不断得到修正,补丁速度随着时间的推移将放缓。 Linus发布新的-rc的内核每周一次,一个正常的系列将介于-rc6-rc9之间,在此之前,内核被认为是不够稳定,然后,最终的2.6.x版本发布。 在此之后,整个过程将重新开始。

这里一个例子,是关于2.6.25开发周期(2008年的所有发布日期):

124

2.6.24稳定版本

210

2.6.25- RC1的,合并窗口关闭

215

2.6.25- RC2测试版

224

2.6.25- RC3发布

34

2.6.25- RC4

39

2.6.25- RC5

316

2.6.25- rc6算法

325

2.6.25- RC7

41

2.6.25- rc8

411

2.6.25- rc9

416

2.6.25稳定版本

开发人员如何决定何时结束开发周期,创造稳定的版本? 最重要的指标采用的是从以前的版本回归名单。 没有bug当然是最好的,但那些造成系统崩溃的bug,在过去被认为是特别严重的工作。 出于这个原因,补丁造成不利回归是被看不起的,而且很可能将在稳定期恢复。

linux开发周期

开发人员的目标是,稳定版本发布前,解决所有已知的回归(regressions)。 在现实世界中,这种完美是难以实现的;这种规模的项目太多的变数。 在那么一刻,推迟最终版本只是使问题变得更糟,太多的变更等待在下一次合并,使合交窗口将变得越来越大,可能在下一次造成更多的回归。 所以大多数2.6.x内核带着一些少数已知的回归,希望他们都不是严重的。

 

一旦一个稳定版本发布,它会交给“维护稳定版本的团队”(“stableteam”)持续维护,目前由GregKroah HartmanChrisWright 组成。 stableteam将不定期发布的稳定版本更新,使用2.6.xy编号方案。 要考虑发布更新,补丁必须(1)修正了重大错误,(2)已被纳入未来发展的核心主线合并。 继续我们的2.6.25例如,本文之前写的:

51

2.6.25.1

56

2.6.25.2

59

2.6.25.3

515

2.6.25.4

67

2.6.25.5

69

2.6.25.6

616

2.6.25.7

621

2.6.25.8

624

2.6.25.9

 

对于一个给定内核的稳定更新大约在6个月之后,稳定版本维护发布只是已经出货的特定的内核的分销者distributors的责任。

2.2:补丁的生命周期

补丁不能从开发者的键盘直接进入主线内核。 还有就是,相反,有些涉及(如果有点非正式)过程,旨在确保每个补丁审查的质量,而且实现了每个补丁的变化对于主线是可取的。 这个过程持续数年后很快发生了轻微的修正,或在大型和有争议的变化的情况下。 许多开发人员挫折来自于对这个过程缺乏了解或企图绕过它。

为减少这种挫折,这份文档将说明如何制作内核补丁。接下来的介绍是一个有点理想化的处理方式。

一个更详细的处理会在后面的章节。该阶段的补丁过程大致如下:

  • 设计。 这是补丁的真正需求-而满足这些需求的方式是作补丁布局。 设计工作往往是不与社区交互条件下做的,但最好是尽可能的开放地去做这个工作,它可以节省大量的重新设计的时间。

  • 早期的审查。 补丁将张贴到相关的邮件列表,这个列表的任何意见将回复给开发者。 如果一切进展顺利,这个过程应该把一个补丁所有重大问题暴露出来,。

  • 更广泛的审查。 当补丁正在为接近列入主线作准备,它将被相关子系统的维护者接受-尽管这并不保证接受该补丁全部进入主线。 该补丁将显示在维护者的子系统树staging树(如下所述)。 当这个过程开始,将会有更广泛的补丁审查和任何由本补丁与其他工作集成所产生的问题将被发现。

  • 合并到主线。 最终,一个成功的补丁将并入主线库由LinusTorvalds管理。 在这个时候,更多的意见和问题可能浮现,开​​发者一定回应并解决这些问题,这很重要。

  • 稳定的版本。 可能受这个补丁影响的用户数量现在是很大的,所以,可能会再一次出现新的问题。

  • 长期维护。 虽然合并后开发人员忘记它的代码,这是绝对有可能的,该行为会在开发社区留在一个很差的印象。合并代码消除了维护的负担,另外也将修复API的变化引起的问题。 但原开发者应继续对代码负责任,如果它要继续长期有用。

由内核开发者(或雇主)作出最大的错误之一就是试图缩短这个过程而直接“合并到主线”。 这种做法往往导致对参与的每个人的挫折感。

 

2.3:补丁如何进入到内核中

恰好有一个人可以合并补丁到主内核库:LinusTorvalds的。 然而,在这12000多个补丁合并到2.6.25内核中去了,只有250名(约2%)是由Linus本人直接确定。 内核项目早已成长为一个大规模开发项目,任何单个人员都不可能监督并在没有帮助的条件下选择补丁。 内核开发者,通过周围的信任链建立了一个中尉系统,解决了这种增长方式带来的问题。内核代码库从逻辑上分解成几个子系统集:网络,具体的架构支持,内存管理,视频设备等。多数子系统有一个指定的维护者,全面对该子系统的代码负责。

 

 这些子系统的维护者是他们所管理的内核部分的看门人(一个松散的方式),他们(通常是)将接受一个纳入主线内核补丁的人。

 

每个子系统的维护者管理他们自己的内核源码树的版本,通常(但肯定不是总是)使用Git源的管理工具。 像Git工具(如quiltMercurial和相关工具)让维护者跟踪的补丁的列表,包括著作权信息和其他元数据。 在任何时候,维护者能够识别,在他或她的源码仓库中,哪些补丁在主线源码没有找到。

 

当合并窗口打开后,顶层的维护者会要求Linus从他们的仓库“拉”他们选定用于合并的补丁。 如果Linus同意,补丁流会流入他的仓库,成为主线内核的一部分。 Linus关注的特定的补丁量在于他拉过来的补丁量。 很显然,有时候,他看起来相当密切。 但是,作为一般规则,Linus信任子系统的维护者不发送坏补丁上来。

 

子系统的维护者,又能够从其他维护者获取补丁。 例如,网络树从一些补丁构建,这些补丁首先从网络设备驱动源码树,无线网络源码树累积。这信息库链条可以任意长,但它很少超过两个或三个环节。 由于每个链中的维护者信任管理较低级别的源码树,这个过程被称为“信任链”。

 

显然,在这样的制度,让补丁进入内核,依赖于找到正确的维护者。 直接发送补丁给Linus通常是不正确的方式。

 

2.4:登台的源码树(stagingtree)

该子系统源码树链条指导补丁流入到内核,但是这又提出了一个有趣的问题:如果有人想看看有哪些补丁正在准备进入下一个合并窗口? 开发者将有兴趣期待其中的变化,看看是否有任何令人担忧的冲突;一个补丁如果更改了一个核心内核函数原型,会与任何使用该功能的旧形式的其他补丁发生冲突。 那些变化放入主线内核前,评审员和测试人员需要访问他们整合表中的变化。 人们可以从任何一个感兴趣的子系统源码拉变化内容,但是这将是一个很大的,而且容易出错的工作。

 

这个答案由(stagingtrees)登台源码树形式获得,登台源码树的子系统源码树收集起来用于测试和审查。最古老的这些源码树由AndrewMorton维护,被称为“-mm”(用于内存管理,这是怎么回事)。 该”-mm”树从一个有长长列表的子系统中集成补丁,它也有一些补丁,旨在帮助调试。

 

除此之外,-mm包含了已由Andrew直接选定的重要的补丁集。 这些修补可能已被张贴在一个邮件列表,或者他们可以作为内核中没有指定的子系统树的一部分。 因此,-mm作为一个子系统的运行最后排序树,如果没有其他明显的进入主线的路径补丁,很可能最终在-mm。 -mm积累的杂项补丁,最终要么被转发到一个适当的子系统树或直接发送给Linus。在典型的开发周期,大约10%的补丁通过-mm加入到内核主线。

 

目前-mm补丁总是可以在头版看到:

http://kernel.org/

想要看到当前-mm状态,可以从“-mmof the moment”源码树中得到:

http://userweb.kernel.org/akpm/ mmotm /

 

使用MMOTM树很可能是一个令人沮丧的经历,这里绝对有可能甚至不会编译通过。其他登台的树(stagingtree),最近开始的是Linux-next,由StephenRothwell维护。 按照设计,Linux-next树是下一个合并窗口关闭后,内核主线所期望呈现的快照。 Linux-next树,当它们整合完成后,在Linux-kernelLinux-next邮件列表中发布,他们可以直接从以下链接下载:

http://www.kernel.org/pub/linux/kernel/people/sfr/linux-next/

一些有关Linux-next信息聚集在:

http://linux.f-seidel.de/linux-next/pmwiki/

 

如何将Linux-next树融入开发过程仍在不断变化。 在撰写本文时,第一个涉及Linux-next2.6.26)的完整的开发周期,即将结束,因此到目前为止,它已被证明是一个宝贵的资源,在合并窗口开始之前,用于查找和解决整合问题。 Linux-next如何运作建立2.6.27合并窗口,更多信息见http://lwn.net/Articles/287155/, 

 

有些开发者已经开始认为Linux-next应该是很好的利用作为未来开发的目标。 Linux-next往往是遥遥领先于主线,对于新的合并内容更具代表性。

 这个想法缺点是,Linux-next的波动性的往往难以使之成为发展的目标。 见http://lwn.net/Articles/289013/ 主题的更多信息,这一点,请耐心等待,Linux-next现在还是有很多地方在不断变化。

 

2.5:工具

由于可以从上面的文字看出,内核开发进程在很大程度上取决于在不同方向的补丁集的能力。 整个事情不会在任何地方工作,没有合适的功能强大的工具。 关于如何使用这些工具教程是远远超出了本文的范围,但有一些方面的链接。

 

到目前为止,主要的源代码管理的内核社区使用的系统是Git。 Git是一个分布式的版本控制系统,并由自由软件社区开发。 将其调整为内核开发很不错,因为它处理大仓库和大量的补丁时表现很好,。 尽管它已经随着时间的推移变得更好,它仍然让人觉得难以学习和使用。熟练使用Git的一些功能,对内核开发几乎是必须要求的,即使他们在自己的工作不使用,那么他们将需要Git来跟上其他开发者(和主线)在做什么。

 

现在几乎所有的Linux发行版本都打包Git。 有一个网页链接:

http://git.or.cz/

这个网页有到文档和教程的链接。 每个人都应该知道,特别是theKernel Hacker’s Guide to git,里面有内核开发的具体信息:

http://linux.yyz.us/git-howto.html

内核开发中不使用Git,最流行的选择是几乎可以肯定的Mercurial

http://www.selenic.com/mercurial/

Mercurial的许多功能要使用Git,但它提供了一个接口,许多人发现更容易使用。

其它值得知道的工具是Quilt

http://savannah.nongnu.org/projects/quilt/

 

Quilt是一个补丁管理系统,而不是源代码管理系统。 它不会追溯时间的历史轨迹,而是跟踪一组特定的变化为主,而不是基于代码库的发展走向。 一些主要的子系统的维护者用Quilt管理补丁并往上传。 对于某些种类源码树管理(如-mm),Quilt是这项工作的最好工具。

 

2.6:邮件列表

一个Linux内核开发的大量工作是通过邮件列表的方式。 不加入至少某个开发社区一个邮件列表,这将是很难充分发挥功能的成员。 但是,对于开发者,Linux邮件列表还表示有潜在风险,其风险是被大量的电子邮件所埋葬,运行在Linux邮件列表,或两者使用的约定相抵触。

 

大多数内核邮件列表在vger.kernel.org;主列表可以在这里找到:

http://vger.kernel.org/vger-lists.html

 

有列出托管在其他地方,虽然,其中一些是在lists.redhat.com

对于核心内核开发邮件列表,当然是Linux-kernel。 这个列表是一个可怕的地方可达每天500消息量,噪音量高,谈话以是严苛的技术问题,参与者并不总是表现出礼貌的高度关注。 但再没有其他地方,内核开发社区将作为一个整体,开发者错过些列表,会错过重要的信息。

 

这里有一些提示,可以帮助使用Linux内核:

  • 已经向一个单独的文件夹发送列表,而不是您的主邮箱。 必须能够忽略持续的时间期限流。

  • 不要试图跟踪每谈话-没有人会这样。 重要的是筛选感兴趣的话题(虽然发现长期进行的对话可能漂离了原来的主题,而没有改变电子邮件的主题行)和参与的人。

  • 不要给巨魔。 如果有人试图挑起愤怒的反应,忽略他们。

  • 当回复到Linux-kernel邮件(或对其他列表)保留抄送:所有相关的头。 这里有一个强有力的理由(如明确要求),你永远不应该删除收件人。 始终确保你的人在抄送回应是:列表。 该公约也使得没有必要明确要求要回复到您的帖子复制。

  • 提问前先搜索列表档案(和整个网络是个整体)。 一些开发者对显然没有做功课的人表现不耐烦。

  • 避免顶部张贴(即凌驾于引用的文字你回应你的答案的做法)。 它使你的回复难以阅读,并产生一个非常不好的印象。

  • 询问正确的邮件列表。 Linux-kernel可能是总的交汇点,但它不是找到所有子系统的开发者的最好的地方,。

 

最后一点-找到正确的邮件列表-是走偏了的初始开发者普遍的出路。 有人在一个在Linux-kernel列表咨询络有关的问题几乎肯定会得到一个礼貌的建议,即到netdev列表邮件咨询,而是因为这是大多数网络开发者光顾的地方。 其他的包括SCSIVideo4LinuxIDEfilesystem等子系统。 最好的地方去寻找邮件列表的地方是与内核源码打包的MAINTAINERS文件

 

2.7:开始内核开发

有关如何开始内核开发是常见的问题-从个人和公司。 同样常见的失误这使得双方的合作开始要难多了。

公司经常聘请知名的开发者获得开发团队开始。 这其实是一种有效的方法。 但它也往往是昂贵的,对于经验丰富的内核开发池这并没有太大的用处。 这是可能使内部开发人员能够加速Linux内核开发速度,考虑到了一些时间的投资。 以这个时间可以赋予一个雇主一个既能够了解内核,又了解公司的开发团队,帮助培训其他人员。

 

 从中期来看,这往往是更有利可图的方法。

个别开发者往往在一个开始的地方迷失是可以理解的。 从一个大项目开始可能被吓着了,一个想要试水的开发者通常从小一点的项目开始。 这样,一些开发者可以进入补丁创建修正拼写错误或轻微的编码风格问题。 不幸的是,这些补丁创建有一定的噪声,其分散了整个开发社区开发的注意力,越来越多,这些是被瞧不起的。 新的开发者希望进入社区,不会得到他们想要的接待。

 

AndrewMorton对有抱负的内核开发者给出了忠告:

1对于所有的内核初学者,项目应该肯定是“确保内核完美地运行在所有机器上,你可以将重点放在你的手中机器”。 通常的方式是,与其他人合作,得到固定起来的东西(这可能需要持续性的),但是这很好-这是一个内核开发的一部分。
  (  http://lwn.net/Articles/283982/  )。

在解决突出问题的情况时,开发者应着眼于回归和一般开放bugs当前的列表。 这里从来不缺需要解决的问题;通过解决这些问题的过程中,开发者将获得经验,同时,建立开发社区需要的方方面面。

3:前期规划

当考虑一个Linux内核的开发项目,它将会是很有诱惑力,并一跃而入,开始编码。但是, 如同任何重要的项目,在写第一行代码前,有很多基础的工作要去做,为成功奠定基础。 花一些时间在早期规划和沟通可以为以后节省更多的时间。

 

3.1:指定问题

如同任何工程项目,一个成功的内核增强开始于对这个要解决的问题的明确说明。 在某些情况下,这一步很简单:例如当一个驱动程序是一个具体的硬件所需要的。 但是,另一方面实际的问题和建议的解决文案很容易让人迷惑,并可能导致问题。

 

想到一个例子:几年前,Linux音频开发者寻求一种方式,来运行不会中途退出或其它人为因素造成系统中过度延迟的应用程序。 该解决方案是,内核模块钩(hook)到Linux安全模块(LSM)框架内,这个模块可以配置给特定的应用程序访问的实时调度。 此模块被实施并被发送到Linux-kernel邮件列表,立即出现了问题。

 

对音频开发人员,这是足够的安全模块,以解决他们的切身问题。 为了更广泛的内核社区,但是,它被视为滥用的LSM框架(这是不打算赋予其权限,而他们本来不会有权限)和对系统稳定性造成风险。 他们的首选解决方案时是通过的短期rlimit长期持续的延迟减低工作来解决实时调度访问。

 

但是,音频社区看不到过去的特定解决方案已实施,他们不愿接受替代品。 这个被否决的结果让那个开发者对整个内核开发过程大所失望,其中一回到音频邮件列表,张贴了这个:

这里有大量的优秀内核开发者,但他们往往得到一大群人的傲慢愚蠢的咆哮。 试图传达用户要求,这些人是在浪费时间。 他们是太“聪明”,以至于不愿意听取这些小凡人。
(  http://lwn.net/Articles/131776/  )。

 

在现实的情况是不同的,内核开发者们更关心系统的稳定性,长期维护问题,并寻找合适的解决问题的办法而不是特定的模块。 这个故事的寓意是把重点放在问题-而不是一个具体的解决方案-在投入创造性代码前,同开发社区共同商讨

所以,当考虑一个内核开发项目,每个人都应该获得一套简易问题的回答:

  • 什么,究竟是哪些问题需要解决?

  • 谁是这个问题影响的用户? 哪些用例应该解决?

  • 内核如何这一问题上显得无能为力?

只有这样,开始考虑可能的解决办法才是有意义的。

 

3.2:及早讨论

当规划一个内核开发项目,在实施前到社区讨论是非常有意义的。 早期沟通可以节省时间,和各种形式的麻烦:

  • 很可能,这个问题是由内核的方式提出,你没有理解。 Linux内核非常庞大,具有很多特性和功能,表现上并不那么直接而明显。 并非所有的核心功能都会被记录,某些一两个可能会,而且有很多容易错过的事情。 作者看了一个完整的驱动程序贴出,重复现有驱动程序,新的作者一直不知道。 重新创造现有的车轮不仅造成浪费,它也不会被接受纳入主线内核。

  • 有可能是提出解决方案,将不会被接受为主线合并元素。 这是为了更好地了解这样的问题,然后再写代码。

  • 其他开发人员也会有对这个问题的思考,这是完全可能的,他们可能有一个更好的解决方案的想法,并在该解决方案上,愿意帮助创建。

 

内核开发社区的多年经验已给我们一个明确的教训:内核代码是闭门造车的设计和开发都具有各种不同的问题,该代码发布到社区时才显露出来。 有时,这些问题很严重,需要几个月或几年的努力,才能使代码符合内核社区的标准。 一些例子包括:

  • Devicescape网络协议栈被设计成单处理器系统的实施。 它不能被合并到主线,直到它满足多处理器系统的需求。 这种改造锁定代码,是一项艰巨的任务,这样一来,这个代码(现在叫mac80211)合并被推迟了一年多。

  • Reiser4文件系统,其中包括很多的功能,在核心内核开发者的意见是应该已经在虚拟文件系统层实施此功能。 这其中也包括没有暴露系统对用户造成的死锁而不能轻易实施的功能。 这些问题给我们的启示是-并拒绝解决其中一些问题-造成的Reiser4退出的内核主线。

  • AppArmor安全模块在这被认为是不安全和不可靠的方法内部的虚拟文件系统数据结构的使用。 此代码已经被大幅改造,但仍然是主线之外。

在这些案例中,一个痛苦的和额外的大量工作本来是可以避免,如果有与一些内核开发者进行初期的讨论。

 

3.3:你跟谁讲话?

当开发人员决定公开他们的计划,接下来的问题是:我们从哪里开始呢? 答案是找到正确的邮件列表和正确的维护者。 对于邮件列表,最好的办法是MAINTAINERS文件寻找有关地方张贴邮件。 如果有一个合适的子系统列表,张贴在这里往往优于在Linux-kernel的张贴,你更有可能到达相关专业开发者的子系统,这个环境可以提供更多有利的支持。

 

寻找维护者可有点困难。 再次,MAINTAINERS文件是开始的地方。 该文件往往并不总是最新的,不过,并非所有的子系统都代表那里。在MAINTAINERS文件中列出的人,可事实上,不是实际上是在目前担任这一角色。 所以,当不知道与谁联系,无疑一个有用的技巧是使用Git(特别是“Git的日志”),看看谁是目前活跃在你感兴趣的子系统。 看看是谁在写补丁,如果任何人,看看是谁在附加签名在这些补丁上。 这些都是最能够帮助人们开始一个新的开发项目。

 

如果一切都失败了,与AndrewMorton 对话,可能成为一种有效的方法来对一个特定的代码跟踪维护者。

 

3.4:什么时候贴邮件?

如果可能的话,在早期阶段张贴你的计划只能是有益的。 描述正在解决的问题,任何如何实施工作的计划。 您可以提供的任何信息,以帮助开发社区对该项目作一些有用的投入。

 

一个令人沮丧的事情可能会发生在这个阶段,不是一个敌对的反应,相反,很少或根本没有反应。 可悲的事实是:(1)内核开发人员比较忙,(2)这里不缺少有宏伟的计划的人,小代码(或甚至是代码展望)支撑他们的不足,以及(3)没有人有义务审查或评论他人发表意见。 如果一个交换意见的请求张贴得到的是很小量的评论回复,不要以为这意味着没有任何兴趣。 不幸的是,你也不能假设有你的想法没有任何问题。在这种情况下,最好的事情就是继续进行下去,让你去了解开发社区。

 

3.5:获得官方购入

如果你的工作是在企业环境中做– 很明显,大多数Linux内核的工作必须从适当的授权管理人员许可后发布您的公司的计划或代码到一个公共的邮件列表。 张贴的代码一直没有清楚地在GPL兼容的授权下发布,可能特别有问题;一个公司的管理和法律工作人员越早同意张贴一个内核开发项目,会受到大家的更好参与。

 

有些读者可能会想在此,他们的核心工作是为了支持一个产品,目前还没有一个正式承认存在的问题。 在公共邮件列表揭示雇主的计划可能不是一个可行的选择。 在这样的情况下,这是值得考虑是否真正需要保密,但往往没有真正需要保持闭门发展计划。

 

不过,也有合法的情况下,公司在开发过程的早期没有必要透露其计划。 有经验的内核开发公司会选择继续开环方式,这样他们将能够避免今后严重的整合问题。 对于没有内部专家的公司,最好的选择往往是聘用外部的开发人员,在不披露的条件下,审查协议的计划。 Linux基金会的运作保密协议计划,旨在帮助这种情况进行运作;更多的信息可以在这里找到:

http://www.linuxfoundation.org/en/NDA_program

这种审查往往是一种足以避免该项目以后无需公开披露的严重问题。

 

4:获取正确的代码

 

这里有许多说法证明一个坚实的以社区为本的设计过程的必要,而任何内核开发项目真正的证据在生成的代码上。 它将由其他开发人员审查和并合并入主线内核树(或不合并)。 因此,这个代码的质量将决定该项目的最终成功。

本节将研究编码过程。 我们将开始一个错误去看看一个数字内核的方法,使开发人员可以。 然后,重点 将转向做正确的事情和工具,可以帮助在这一努力中。

 

4.1:陷阱

  • 编码风格

内核早就有一个标准的编码风格,如Documentation/CodingStyle描述。 对于大部分时间,在该文件中描述的政策顶多是个建议。 因此,内核中的大量代码不符合编码风格指导方针。 这些代码的存在导致两个独立的内核开发的危害。

 

其中第一项就是相信,内核编码标准并不重要,并没有得到执行。 事情的真相是,添加新的代码对内核是非常困难的,如果这些代码是不按标准编码,许多开发者将会要求他们在审查代码之前,重新格式化代码。 一个像内核代码那样大的库需要一些统一风格代码,这使开发人员能够快速了解它的任何部分的。 因此,没有任何空间给奇怪格式的代码。

 

偶尔,内核的编码风格会遇到与雇主的授权风格冲突。 在这种情况下,代码可以合并之前,内核的风格应该占上风。 放入内核代码意味着放弃了多少控制度– 包括控制代码如何被格式化。

另一个陷阱是假设的代码已经在内核中急需的编码风格修复的需要。 开发者可以开始产生重新格式化补丁作为熟悉的过程,方式或作为获得他们的名字变更记录到内核的方式-或两者兼而有之。 但纯粹的编码风格修复被看作是由开发社区噪音,他们往往会得到一个冰冷的接待。 所以,这种类型补丁最好避免。由于工作等原因,很自然地解决​​了一段代码风格,但编码风格的变化不应该为自己着想制成。

文件的编码方式也应该不被理解为一种绝对的法律,永远无法逾越。 如果有一个很好的理由去反对这种风格(例如,一行如果分裂以适应在80列的限制,这使得可读性变得更差),那么就去做好了。

 

  • 抽象层

计算机科学教授教给了学生,使抽象层成为广泛使用代表灵活性和信息隐藏的名称。当然,内核广泛使用使用抽象的概念,没有这样的项目,涉及几百万行代码,可以不这样做而生存。

但经验证明,过量或过早抽象,与过早的优化一样,是有害的。应适量地使用抽象,而不要过。

 

一个简单的层面上,考虑一个函数,它总是有一个参数始终通过为零被所有调用者调用。人们可以保留这样的说法,以防万一有人最终需要用它提供额外的灵活性。到那个时候,虽然这是很有可能实现的不错的代码,也可能这个额外的参数会在一些微妙的方式中崩溃,这些从来没有注意到– 因为它从来没有使用过。

 

或者,当需要时提供额外的灵活性,它没有这样做,与程序员的早期期望相匹配。内核开发人员将定期提交补丁删除未使用的传递参数,他们应在一般情况下,首先不添加它。

其中隐藏抽象层访问硬件-往往是允许大部分驱动在多数操作系统中使用的-尤其是不可取的。 这种晦涩的代码层,将在性能表现上受到惩罚,他们不属于在Linux内核。

另一方面,如果你发现自己从另一个内核子系统复制大量的代码,这样是否要问,拉出那部分代码到一个单独的代码库,或在更高的软件分层执行这一功能,其实更有意义。 整个内核复制大量相同的代码没有什么太大的价值。

 

  • ifdef和预处理普遍使用

C预处理器似乎提出了一个强大的诱人的功能,C程序员以此来有效地编码源文件,极大地提高了它的灵活性。 但预处理器不是C,大量使用它会造成代码阅读困难,编译器检查代码的正确性也将更为困难。 大量预处理使用几乎总是作为一个代码标志,上面的代码需要一些清理工作。

在内核中使用#ifdef条件编译,确实是一个强大的功能。 但有一点希望看到你的代码在使用#ifdef块时,宽松一点分布。 作为一般规则,只要有可能,#ifdef的使用应限于头文件。 有条件编译的代码可以限定在函数,如果代码是不存在,直接成了空函数。 编译器将悄然地对空函数调用进行优化。 其结果将是更干净的代码,更容易被跟随。

C预处理宏呈现出多种可能的危害,包括表达式多种赋值的副作用和无类型安全问题。 如果你被其吸引来定义一个宏,而考虑创建一个内联函数替代, 一个代码,结果将是相同的,但内联函数更易于阅读,不用多次对传递参数进行赋值,并允许编译器对传递参数和返回值执行类型检查。

 

  • 内联函数

内联函数会表现出自己的危险。 内联函数可以避免内部函数调用,而直接填充源文件,程序员会因此迷恋其能感受到的效率提升。但是, 这些函数实际上也可能降低性能。 由于他们的代码在每次调用点复制,他们最终已编译的内核的大小将会爆炸。

反过来,对处理器的内存高速缓存建立了新的压力,将显著减慢执行速度。 内联函数,其使用规则是,应该是相当小,比较少用。 一个函数调用的开销,毕竟不是那么高,内联函数大量使用是过早的优化的一个典型的例子。

 

一般情况下,内核程序员忽略了缓存影响的危险。 在课堂上,初学的数据结构经典的时间/空间的权衡,往往并不适用于现代的硬件。 空间就是时间,一个较大的程序运行速度往往慢于一个更紧凑。

  • 锁定

20065月的“Devicescape”网络堆栈,在GPL授权下大张旗鼓地发布,并提出在主线内核中包含可用。 此次捐赠是值得欢迎的,在Linux的无线网络的支持被认为严格来说是不合格的,Devicescape堆栈承诺可以解决这种状态。 然而,这个代码没有真正进入主线,直到20076月(2.6.22)中。 发生了什么事?

很多的迹像显示,这些代码是在企业封闭状态下开发的。有一个特别大的问题是,它不是设计给多处理器系统工作。 在网络协议栈(现在叫mac80211)可以合并之前,需要完全修改锁定方案。

曾几何时,Linux内核代码可以不用担心开发的多处理器并行系统会出现问题。 不过,现在这个文档就正在双核笔记本电脑上写。 即使在单处理器系统,目前的一些工作将提高反应能力,在内核将提高并发水平。 在写内核代码时,可以不考虑有关锁定问题的日子早已过去。

任何资源(数据结构,硬件寄存器等),可能会访问多个线程同时必须加保护锁。 新的代码写入应考虑到这一要求;改造锁定这件事是一个较为困难的任务。 内核开发人员应该花时间来了解可用的锁原语,应尽量选择正确的工具以胜任这个工作。不重视并发问题处理的代码将很难进入主线。

  • 回归

值得一提的最终危害是这样的:它可能被诱惑做出改变(这可能带来很大的改进),导致现有的一些用户崩溃。 这种变化被称为一个“回归”,回归已经成为主线内核中最不受欢迎的。 除了少数例外,这种回归不能及时修复,这部分代码更新将会被拒绝。 最好首先避免出现回归。

 

人们常常认为,,如果可以正常运行的多于出现问题的,这应该是一个合理的回归。 为什么不作改变,如果它带来的新功能,对十个系统每一个都会崩溃? 最好的回答这个问题是由Linus阐述20077月:

所以我们不解决引入新的错误带来的bug, 这是疯狂的谎言,没人会知道,如果你确实做任何实际进展。 它是前进两步,退一步,或者前进一步退两步?
(  http://lwn.net/Articles/243460/  )。

一种特别不受欢迎的回归类型是更改到用户空间的ABI排序。 一旦一个接口已出口到用户空间,它必须无限期地予以支持。 这一事实使得用户空间接口的创建,特别具有挑战性:因为他们无法以不兼容的方法来改变,这必须在第一时间完成。 基于这个原因,大量的思考,清晰的文档,以及用户空间接口广泛的审查始终是必需的。

 

4.2:代码检查工具

现在,至少无差错编写代码仍然是理想化的,是我们很少有人能达到。 我们可以希望做的是,在我们代码进入主线内核中去之前,捕捉并解决尽可能多的错误。 为此,内核开发人员已经把一系列令人印象深刻的工具,可以自动捕捉各种模糊问题。由电脑抓到的任何问题是,以后不会再折磨用户,所以它是合乎道理的自动化工具,应尽可能使用。

 

第一步是简单地听从编译器产生的警告。 现在的gcc版本可以检测(和警告)大量潜在的错误。 很多时候,这些警告点针对实际问题。作为一项规则, 应提交审查的代码应不会产生任何编译器警告。 当处理警告,注意了解真实的原因,尽量避免简单“修复”不解决其真正原因,而使警告消失。

 

请注意,并非所有编译器警告是默认启用的。 编译内核时,用”makeEXTRA_CFLAGS=- W “,以获取完整的一套警告。

内核提供了几个配置选项于打开调试功能,其中有大部分是在“kernelhacking”子菜单中找到。 这几个选项应该打开,用于开发或测试的任何内核。 特别是应该打开:

  • ENABLE_WARN_DEPRECATED , ENABLE_MUST_CHECK FRAME_WARN,对问题能得到一个额外的警告,如使用过时的接口或忽视了一个重要的函数返回值。 这些警告输出产生可能比较冗长,但人们不必担心内核其它部分的警告。

  • DEBUG_OBJECTS 将添加代码来跟踪内核各种对象的生命期,并在违反秩序时提出警告。 如果要添加一个子系统,这个子系统将创建(导出)它自己的复杂对象,可以考虑增加支持对象调试的一些基本框架。

  • DEBUG_SLAB 可以发现各种错误的内存分配和使用,它应该是用在大多数内核。

  • DEBUG_SPINLOCK , DEBUG_SPINLOCK_SLEEP 和 DEBUG_MUTEXES 会发现一些通常的错误锁定。

 

有相当多的其它调试选项,其中一些将在下面讨论。 其中有些对性能有显著的影响,不应该在所有的时间使用。 但花一段时间学习一些可用的选项,可能会在短期内给您以数倍的回报。

 

较重要的调试工具之一是锁定检查,或“lockdep。” 此工具将跟踪采集系统中的每个锁(自旋锁或Mutex)的获取与释放,锁的获取与释放的顺序彼此相对,如目前中断的环境等。 它可以确保总是以相同的顺序获得锁,同一个中断的假设适用于所有情况,等等。 换句话说,lockdep可以用在多种场景中,其系统可能在极少数场合出现死锁。 在部署系统时,(对开发人员和用户)这种问题可能是痛苦的;lockdep允许他们在一个自动化的方式提前发现。 存在任何非平凡锁定的代码应运行lockdep检查,才能提交

作为一个勤奋的内核程序员,毫无疑问,你会检查任何操作(如内存分配)返回状态,它可能会是失败的。 事实是由此产生的故障恢复路径,很可能是完全去除没有测试代码。 未经测试的代码往往是引起故障的代码,如果所有的错误处理路径已经行使了几次,你可能会更加有信心你的代码。

内核恰恰提供了故障注入的框架,尤其是在内存分配的参与。 随着故障注入启用,可配置的内存分配比例将会失败,这些失败可以被限制到一个特定的代码范围。 故障注入启用运行时允许程序员看到代码在不好环境中如何响应。 请参看Documentation/fault-injection.text以取得更多关于如何使用这个方法的信息。

 

sparse”静态分析工具可以找到其它类型的错误。程序员会被警告用户空间与内核空间的地址混乱,big-endiansamll-endian数值混合,整数的值传递一些预期的比特位标志,等等。 Spare必须单独安装(如果您的经销商没有打包这个软件,也可以在http://www.kernel.org/pub/software/devel/sparse/ 找到),它可以将代码加入“C= 1“运行您的make命令。

 

其他种类的错误最好通过在其他架构编译你的代码来发现。 如果你没有碰巧有一个S/390的系统或Blackfin处理器的开发板,你仍然可以执行的编译步骤。 对于x86系统的交叉编译器大集可以在下面链接中找到:

http://www.kernel.org/pub/tool​​s/crosstool/

花一些时间安装和使用这些编译器将可避免以后的尴尬。

 

4.3:文档

文档经常比内核开发规则异常。 即便如此,充足的文件将有助于缓解新的代码合并到内核困难,让其他开发者更容易明白,并将为您的用户很有所帮助。 在许多情况下,额外的文档基本上成为强制性的。

 

任何补丁文件第一份相关的相关的文档是changelog。 Log应描述得到解决的问题,解决方案的形式,修正补丁工作的人,任何有关性能的影响,以及任何其他对了解补丁有帮助的内容。

 

任何代码增加了一个新的用户空间接口-包括新的sysfs/proc文件-应在文档中描述这些接口,使用户空间开发人员知道这是什么接口。 请参看Documentation/ ABI/README文档需要如何的格式,以及需要提供哪些信息说明。

 

文件Documentation/kernel-parameters.txt介绍了内核的启动时的所有参数。 任何补丁,增加了新的参数应添加相应的条目,在此文件。

任何新的配置选项必须附有说明文字,清楚地说明了选项,用户可能要选择它们。

 

许多子系统的内部API的信息被记录以特殊格式的批注方式,这些批注可提取出来并以“kernel-doc”脚本的多种方式格式化。 如果你是在一个子系统,具有kernel-doc注,你应该保留并添加它们,并酌情添加外部可用的功能。 即使在没有这些文档的地方,未来没有增加kernel-doc批注也不会有伤害,事实上,这可能是一个开始内核开发很有用的行为。 这些批注的格式,以及一些关于如何创建kernel-doc模板的信息,可以在Documentation/kernel-doc-nano-HOWTO.txt找到。

 

如果谁通过大量阅读现有的内核代码将注意到,很多时候,批注显著缺乏。 再次,新代码的期望高于他们在过去的人;合并没有注释的代码会更难。 尽管如此,很少有冗长的注释代码欲望,。 该代码应本身是可读的,批注能解释代码更微妙的一些方面。

 

有些事情应始终进行批注。 采用内存障栅(memorybarries应当附有解释为什么这个障栅是必要。 数据结构的锁定规则是通常需要说明的地方。 主要的数据结构需要在一般的综合文件说明。

代码分离的比特位之间,非显而易见的依赖应该指出。 任何可能诱使代码监管人作出不正确的“清理”的,需要一个批注说明为什么这个样子做, 等等。

 

4.3:文档

文档经常比内核开发规则异常。 即便如此,充足的文件将有助于缓解新的代码合并到内核困难,让其他开发者更容易明白,并将为您的用户很有所帮助。 在许多情况下,额外的文档基本上成为强制性的。

 

任何补丁文件第一份相关的相关的文档是changelog。 Log应描述得到解决的问题,解决方案的形式,修正补丁工作的人,任何有关性能的影响,以及任何其他对了解补丁有帮助的内容。

 

任何代码增加了一个新的用户空间接口-包括新的sysfs/proc文件-应在文档中描述这些接口,使用户空间开发人员知道这是什么接口。 请参看Documentation/ ABI/README文档需要如何的格式,以及需要提供哪些信息说明。

 

文件Documentation/kernel-parameters.txt介绍了内核的启动时的所有参数。 任何补丁,增加了新的参数应添加相应的条目,在此文件。

任何新的配置选项必须附有说明文字,清楚地说明了选项,用户可能要选择它们。

 

许多子系统的内部API的信息被记录以特殊格式的批注方式,这些批注可提取出来并以“kernel-doc”脚本的多种方式格式化。 如果你是在一个子系统,具有kernel-doc注,你应该保留并添加它们,并酌情添加外部可用的功能。 即使在没有这些文档的地方,未来没有增加kernel-doc批注也不会有伤害,事实上,这可能是一个开始内核开发很有用的行为。 这些批注的格式,以及一些关于如何创建kernel-doc模板的信息,可以在Documentation/kernel-doc-nano-HOWTO.txt找到。

 

如果谁通过大量阅读现有的内核代码将注意到,很多时候,批注显著缺乏。 再次,新代码的期望高于他们在过去的人;合并没有注释的代码会更难。 尽管如此,很少有冗长的注释代码欲望,。 该代码应本身是可读的,批注能解释代码更微妙的一些方面。

 

有些事情应始终进行批注。 采用内存障栅(memorybarries应当附有解释为什么这个障栅是必要。 数据结构的锁定规则是通常需要说明的地方。 主要的数据结构需要在一般的综合文件说明。

代码分离的比特位之间,非显而易见的依赖应该指出。 任何可能诱使代码监管人作出不正确的“清理”的,需要一个批注说明为什么这个样子做, 等等。

 

4.4:内部API的变化

由内核到用户空间提供的二进制接口不能被打破,除了在最严重的情况下。 内核的内部编程接口,而是具有高度流动性,并且可以在需要时改变。 如果你发现自己有工作,围绕一个核心的API,或根本不使用特定的功能,因为它不符合您的需求,这可能是一个迹象,表明该API需要改变。 作为一个内核开发人员,你有权作出这样的变化。

当然,这样有一些缺点。 API可以发生变化,但他们需要用得其所。 因此,任何补丁使内部API发生变化,应附有说明描述它一个什么样的变化,以及为什么有必要的改变。 这种变化也应该变成一个单独的补丁,而不是埋在一个较大的补丁之中。

另一个缺点是,开发者改变了内部API,也必须修正内核源码树内的因你的改变而崩溃的代码,这是你的任务。 对于广泛使用的功能,这一责任可能导致数以百计或数以千计的变化-其中许多可能与其他开发者完成的工作相冲突。 不用说,这可能是一个庞大的工作,所以最好能确定,你的理由是坚实的。

 

作出不兼容的API改变时,只要有可能,确保编译器捕获到你一直没有更新你的代码。 这将帮助你确保你已经找到在内源源码树对该接口的使用。 它也将提醒开发者源码树外(out-of-tree)代码有变化,他们需要自己应对。 支持源码树外代码,不是内核开发人员需要担心的,但我们也不必担心源码树外代码要要更难开发。

 

 后面的内容请见如何加入Linux社区开发(译)二:

http://blog.csdn.net/ccwwff/article/details/6590696



GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐