分类 技术志 下的文章

如何加入Linux内核开发社区(6)

本文翻译自The Linux Foundation的《How to Participate in the Linux Community》(基于2012-03-21最新版本),原作者为Jonathan Corbet(corbet@lwn.net)。 下面是该文章第六章节的中译文。

6、将补丁工作进行到底

此时此刻,你已经遵循了这里到目前为止给出的所有指导原则,并且由于你自己的工程技能,你已经发布一系列完美的补丁。但即使是经验丰富的内核开发者也可能 会犯的一个最大的错误是断定他们的工作已经结束。事实上,发布补丁象征着你的工作已经过渡到了开发过程下一个阶段,很可能还有相当多的工作需要去完成。

很少有补丁可以好到在第一次发布后就没有改进余地了。内核开发过程深知这一事实,并且因此重点关注已发布代码的改进。内核开发社区期望作为补丁代码作者的 你能够与社区一起工作来保证你的代码可以达到内核的质量标准。如果未能很好地参与到这个过程中将很可能导致你的补丁无法进入到内核主线。

6.1、与评审者一起工作

任何一个有意义的补丁都会引来一些评论,这些评论是其他开发者对你的补丁进行代码评审时得出的。对于许多开发者来说,与评审者一起工作可能是整个内核开发过程中最令人胆颤心惊的环节了。但如果你记住一些事情,你的工作可能会变得轻松许多:

  * 如果你对补丁进行了很好地解释,评审者就会理解它的价值以及为何你在创建补丁时遇到了困难。但这些都无法阻止评审者提出一个基础问题:五年或十年后,维护 一个合并了这份代码的内核将会是一个什么样子?你可能被要求进行许多改变–从代码风格改进到大量的代码重写–这些改变都基于这样的一种共识:从现在起 的十年间,Linux将仍然活着并依旧在开发中。

  * 代码评审是一个困难的工作,并且是一个相对费力不讨好的工作;人们会记住谁编写了内核代码,但那些评审代码的人却很少有持久的名声。因此,评审可能会变得 脾气暴躁,特别是当他们看到同一个错误被一再地犯的时候。如果你收到一个看似生气、出言不逊或完全无礼的评审意见,那么要抑制住你本能地回复的冲动。代码 评审只是针对代码,而不是针对人,并且代码评审者从其个人角度来说并非是要攻击你。

  * 同样,代码评审者不会为了推广他们雇主的方案而故意中伤你的方案。内核开发者常常期望能从现在起在内核上工作很多年,但他们深知他们的雇主可能会变化。他们工作的真实目的毫无疑问是为了创造一个他们所能创造的最好的内核;他们不会设法给雇主的竞争对手制造不适。

所有这一切归结起来就是,当评审者发送评论给你时,你需要关注这些技术意见。不要让他们的表达方式或你的傲慢阻碍这个过程的发生。当你收到针对你的补丁的 评审意见时,花些时间去理解评审者所表达的意思。如果可能的话,修正那些评审者请求你修正的问题。并且回应评审者:对他们的评审表示感谢,并且说明你将如 何回答他们的问题。

请注意,你无需同意每个评审者建议的改变。如果你认为评审者误解了你的代码,那么解释你的代码的真实意图给评审者。如果你对某个建议的改变存在技术上的异 议的话,解释你的异议并证明你的问题解决方案。如果你的解释有道理,评审者会接受它们的。但如果你的解释被证明没有说服力,特别是如果其他开发者开始认同 那个评审者的意见时,花些时间重新考虑一下吧。你很容易被你自己的问题解决方案所蒙蔽,甚至你可能没有意识到一些事情从根本上就是错误的,或者也许你根本 没有解决那个问题。

一个致命的错误是忽略那些评审意见并期望他们能消失。他们不会消失。如果你重新发布的代码没有处理之前收到的评审意见,你很可能会发现你的补丁将无处可去。

谈到重新发布代码:请记住评审者是不会记住你上一轮发布的代码的所有细节的。因此一个好的方法是提醒评审者之前提出的问题以及你是如何处理这些问题的;补 丁的变更日志(changelog)是一个用来记录这类信息的很好的地方。评审者不应该非得通过搜索邮件列表的归档才能重新了解到他们上一次所提出的意 见;如果你一开始就帮助他们重新了解上次的问题,那么在他们重新评审你的代码时将会有一个更为好的心情。   

如果你已经努力尝试做对每件事,但事情依旧无法进行下去怎么办?大多数技术上的异议都可以通过交流讨论解决,但有时候,有人不得不作出决定。如果你的确认 为这个决定不应该由你来作出,那么你总是可以尝试向更高一级的开发者寻求帮助。对于本文来说,更高一级的人可能是Andrew Morton。Andrew在内核开发社区十分受尊敬;他常常可以将那些看上去堵塞地毫无希望的情况疏通开来。要记住,他当然也可能不同意你的看法。

6.2、接下来会发生什么

如果一个补丁加入到内核被认为是件好事,且一旦大多数评审意见都已经被解决掉了,接下来的一步通常是进入一个子系统维护者的源码树中。加入的方式因不同子 系统而异;每个维护者都有其自己的工作方式。尤其是,可能有不止一个源码树–可能一个专用于为下一个合并窗口的准备的补丁,另一个用与更长期的工作。

对于那些没有适用的子系统源码树(例如内存管理补丁)的补丁来说,默认的源码树常常最终是-mm树。那些对多个子系统有影响的补丁也可能最终提交到-mm树中。

合入子系统源码树后的补丁将会拥有一个更高级别的可见性。现在工作在那颗源码树上的其他开发者将会默认得到这个补丁。子系统树通常也为-mm和 linux-next两个源码树提供补丁,这将使补丁的内容对整个开发社区可见。此时,你很有很可能从一批新的评审者那里获得更多的评审问题;你需要答复 这些问题,就像之前的那轮一样。

此时还有可能发生的是与其他开发者所完成的工作的冲突,这取决于你的补丁的性质。最坏的情况下,严重的冲突可能导致一些工作被放在次要的位置,而剩下的补 丁可能最终成型并被合并到内核中。其他时间,冲突解决将涉及到与其他开发者一起工作并且可能涉及在源码树间移动补丁以保证所有事情都能按规则地应用。这种 工作很可能是一种痛苦,但你应该知足了:在linux-next树出现之前,这些冲突往往只是在合并窗口打开期间出现,你必须尽快处理掉这些冲突。而现 在,在合并窗口打开之前开发者可以从容不迫地解决这些冲突。

某天,如果一切顺利,你登录主机并且会看到你的补丁已经被合并到内核主线了。恭喜恭喜!但是,一旦庆祝结束(并且你已经将你自己加入到MAINTAINERS文件),记住一个重要的事实是值得的,那就是:工作依旧没有结束。合并到内核主线将带来其自己的挑战。

首先,你的补丁的可见性已经再一次增加了。你可能会收到新的一轮评审意见,这些意见来自于那些之前不曾知道你的补丁的开发者们。你很可能忽略这些意见,因 为已经没有关于代码合并的问题了。但抵制住这种诱惑;对于那些提出问题或建议的开发者来说,你仍然需要保持处于积极相应的状态。

但更为重要的是:合并到内核主线后你的代码将被更多的测试人员获得。即使你贡献的是一个尚不可用的硬件的驱动程序,你会惊讶于有这么多人将你的代码构建到他们的内核当中。并且当然,哪里有测试人员,哪里就会有bug报告产生。

最坏的bug报告类型是regression。如果你的补丁导致了一个regression,你就会发现有许多双令人不舒服的眼睛在注视着 你;regression需要被尽早修复。如果你不情愿或没有能力修复这个regression(并且没有人为你做这件事),那么在内核稳定期,你的补丁 几乎可以肯定会被移除。因无法修复regression而导致补丁被从内核拉出(pull),除了否定了之前你为补丁进入主线而做的所有工作之外,还很可 能大大增加你的后续工作被合并的难度。

在处理完若干regressions之后,可能还有另外一些普通bug需要处理。内核稳定期是修正这些bug以及确保你首次出现在某内核主线版本的代码尽 可能的稳定可靠的最好时机。因此,请回答bug报告,并尽可能地修正问题。内核稳定期就是为此而设立的;一旦旧补丁中所有问题都被处理完毕,你就能够开始 创建一些绝妙的新补丁了。

不要忘了其他里程碑也可能创建bug报告:下一个主线稳定版发布、当一些重要的发行版生产商得到了包含你的补丁的内核版本等等。继续响应这些报告事关你在 工作中的自豪感。然而,如果感到动力不足,这点也是值得考虑一下的:开发社区会记住那些在合并代码后对他们自己的代码失去兴趣的开发者。下次你再发布一个 补丁,他们会在你过后不会继续维护它的假定下对该补丁进行评估。

6.3、其他可能发生的事情

有一天,你会打开你的邮件客户端程序并看到某人给你邮寄了一份针对你的代码的补丁。归根结底,这是将你的代码公开发布的好处之一。如果你认同这个补丁,你 可以将它转发给子系统维护者(确认包含一个恰当的From:行以保证其归属是正确的,并且增加一个你自己的signoff),或以一个Acked-by: 回应并让原始发布者发送给上面的维护者。

如果你不认同这个补丁,那么发送一个礼貌的回应并解释你不认同的原因。如果可能的话,告诉作者需要做哪些改动你才会接受该补丁。对于那些被代码作者和维护 者抵制的补丁来说,合并是有一定阻力的,不过也就仅此而已。如果你对某杰出的工作的阻止被认为是没有必要的,那么那些补丁最终还是会绕过你并进入主线。在 Linux内核中,没有人拥有代码的绝对否决权,也许除了Linus。

在极少的情况下,你可能会看到完全不同的情况:另外一个开发者针对你的问题发布了一个不同的解决方法。那一刻,两个补丁中的一个将无法被合并,并且"我的 是第一个"不被认为是一个令人信服的技术参数。如果某个其他人的补丁代替了你的并进入到了主线,那真的只有一种回应的方式了:为你的问题被解决掉而高兴并 继续你的工作。将某人的工作以这种方式丢在一边可能是伤人感情和令人泄气的,但是在忘记了谁的补丁被真正合并了之后,开发社区会记住你的回应。

如何加入Linux内核开发社区(5)

本文翻译自The Linux Foundation的《How to Participate in the Linux Community》(基于2012-03-21最新版本),原作者为Jonathan Corbet(corbet@lwn.net)。 下面是该文章第五章节的中译文。

 
5、发布补丁
 
迟早有一天你的工作将提交到开发社区进行评审,并最终合入内核主线。不出所料,内核开发社区在发布补丁方面已经逐步形成了一套约定和程序;遵循这 些约定和程序将使得开发者们的工作变得更加轻松。本文将尝试适当详尽地对这方面的内容进行说明;更多内容可以参考内核文档目录下的 SubmittingPatches、SubmittingDrivers和SubmitChecklist文档。
 
5.1、何时发布
 
一直存在这样一种诱惑:在补丁完全"具备条件"之前不要发布补丁。对于简单的补丁,这不是问题。但如果补丁的工作比较复杂,则在补丁完成前,很多事情需要从开发社区获取的反馈中得到。因此你应该考虑将正在进行中的工作发布给社区,或者甚至可以提供一个可用的git源码树,让那些对你的补丁感兴趣的开发者随时了解到你的工作进展。
 
当发布一些尚不具备被合入内核条件的代码时,最好在发布时如实告知社区。同时要说明还有哪些主要工作尚待去做以及所有已知的问题。与已完成的补丁相比,那些已知尚未完成的补丁获得的青睐更少,但那些确实提出想法的人能够帮助你始终工作在正确的方向上。
 
5.2、在补丁创建之前
 
在你考虑将补丁发布到开发社区之前,有一些事情是需要预先做的,这些事情包括:
 
  * 尽你所能的对补丁代码进行测试。充分利用内核调试工具,确保内核可以在所有合理的配置选项组合下编译,使用跨平台编译器进行不同体系的构建,等等。
 
  * 确保你的代码与内核编码风格准则兼容。
 
  * 你的变化会对内核性能有影响吗?如果有的话,你应该运行基准测试来看看你的改变对内核的具体影响(或带来的好处);补丁中应该包含这个测试结果的总结。
 
  * 确保你有权发布这个补丁代码。如果代码是为某个雇佣者开发的,雇佣者很可能才是这段代码的真正拥有者,那么雇佣者必须同意补丁在GPL许可证下发布。
 
一般来说,在发布代码之前多做一些考虑总是会在短时间内让你的付出收到回报的。
 
5.3、补丁准备
 
补丁发布准备的工作量可能十分巨大,不过,再重申一遍,即便是短期内尝试在这个阶段节省时间通常也是不可取的。
 
补丁必须是为某一个特定的内核版本而准备的。通常,补丁应该基于linus的git树中的当前主线版本。但为了能让补丁得到更为广泛的测试和评审,制作针对-mm、linux-next或某个子系统树的补丁版本可能会变得很必要。针对其他源码树的补丁可能需要大量工作来解决代码冲突以及处理API的改变,这取决于你的补丁所在的领域以及其他方面的当前进展情况。
 
只有最简单的改变才应该以一个单独的补丁形式提供;其他所有补丁都应该由一系列合理的改变组成。拆分补丁是一门艺术;一些开发者花费很长时间考虑如何以一种开发社区期望的方式进行补丁拆分。下面是一些经验法则,但却相当有帮助:
 
  * 你发布的补丁序列决不应该仅仅是你的版本控制系统下的一系列改变。相反,你应该考虑这些改变的最终形式,将他们分成有意义的若干部分。开发者只对离散的、自完备的改变感兴趣,而不是你提供的这些改变的路径信息。
 
  * 每个逻辑上独立的改变都应该以一个单独的补丁提供。这些改变可小("为这个结构体增加一个字段")可大(例如,增加一个重要的新驱动程序),但它们都应该是小概念的并且可用一行文字描述的。每个补丁所带来的改变都应该可以被独立评审和独立验证的。
 
  * 这里再次重申一下上面的准则:不要将不同类型的改变混在一个补丁中。如果一个单独的补丁修复了一个极其重要的安全bug、重新调整了一些结构体并且重新对代码进行了格式化,那么这个补丁很有可能被置之不理,这个重要的修复也将会丢失。
 
  * 每个补丁都应该生产出一个可以正确编译和运行的内核;即使你的补丁序列在中间被打断,结果仍然应该是一个可工作的内核。部分应用一个补丁序列是一种常见的情况,尤其是当"git bisect"工具被用于查找regression时;如果补丁序列被打断的结果是一个损坏的内核,则会导致那些参与追查内核问题的开发者和用户的工作更加困难。
 
  * 但也不要做的太过分。最近一个开发者将一个文件的多处修改放在500个补丁中发布 — 这一行为并没有使他成为内核邮件列表上最受欢迎的人。只要仍然包含一个单一的*逻辑*改变,一个单一的补丁也可以适当地大些。
 
  * 人们可能很想通过一系列的补丁来为内核增加一个完整的新基础设施,但直到这个系列的最后一个补丁生效,这个新设施才好用。这种想法应该尽可能的避免;如果这一系列补丁新增了regression,折半问题查找方法会把最后一个补丁视为导致问题罪魁祸首,即使真正的bug发生在别处。所以无论何时,添加了新代码的补丁都应该使得那些代码立即可用。
 
创建一个完美补丁的工作可能是一个令人沮丧的过程,这个过程将在"真正的编码工作"完成之后花费大量的时间和思考。但一旦正确地完成,你会感觉这个时间花费是值得的。
 
5.4、补丁格式化
 
现在,你已经有了一系列准备发布的完美补丁,但工作还远没有完成。每个补丁都需要被格式化为一条消息,这条消息可以快速清晰地将补丁的目的阐述给其他人。因而,每个补丁将由下面几个部分组成:
 
  * 一个可选的"From"行,用于指出补丁作者的名字。这一行只是在你通过mail对别人的补丁进行评论时才是必要的,并且在有疑问时加上这一行没有什么坏处。
 
  * 一行关于补丁做什么的描述。这行消息应该足以让一个读者在无需其他上下文信息提示的情况下确定这个补丁的范围;它就是将记录在简易格式的变更日志(changelog)中的那一行。这个消息的格式通常是以相关子系统的名字开头,后面跟随着这个补丁的目的。例如:
 
     gpio: fix build on CONFIG_GPIO_SYSFS=n
 
  * 在补丁内容的详细描述之后跟随一个空行。补丁内容描述的长度可以根据需要而定;这份描述应该说明补丁做了哪些事情以及为何该补丁应该被应用于内核。
 
  * 一个或多个标签(tag)行,至少应该有一个来自补丁作者的signed-off-by:行。接下来会有对标签(tags)的更为详细的说明。
 
上面的三项通常应该是提交补丁代码到版本控制系统时所使用的文本。后面跟着:
 
  * 补丁本身,使用统一标准的("-u")补丁格式。结合"-p"选项使用diff会将函数名字与改变相关联,结果可以使得补丁更易于被其他人阅读。
 
你应该避免在补丁中包含无关文件(比如那些由编译过程产生的文件或编辑器备份文件)的改变。Documentation目录下"dontdiff"在这方面可以提供帮助;在执行diff命令时使用"-X"选项。
 
上面提到的标签(tag)用于描述不同开发者是如何与此补丁的开发相关联的。在SubmittingPatches文档中有关于这方面的详细说明;下面是一个简要的总结。每行的格式是这样的:
 
  tag: Full Name <email address> optional-other-stuff
 
常用的标签如下:
 
  * Signed-off-by: 这是一个开发者有权提交可以被内核合并的补丁的证明。表示同意"Developer's Certificate of Origin"协议,该协议的全部文本内容可以在Documentation/SubmittingPatches中找到。没有正确signoff的代码将无法合并到内核主线中去。
 
  * Acked-by: 表明另外一名开发者(通常是相关代码的维护者)认可该补丁适合合并到内核中。
 
  * Tested-by: 说明这个人已经测试过这个补丁并发现它可以工作。
 
  * Reviewed-by: 这个签名的开发者已经对这个补丁的正确性进行了评审;在Documentation/SubmittingPatches中有关于"Reviewer's statement(评审者的声明)"的详尽描述。
 
  * Reported-by: 说明了这个补丁所修正的问题是哪个用户提出的;这个标签用于赞扬那些对内核代码进行测试并让大家知道什么时候内核无法正确工作的人(常常是未得到正确评价的)。
 
  * Cc: 列出哪些人会接收到一份补丁的拷贝并有机会对补丁进行评判。
 
在向你的补丁中添加标签时要小心:只有Cc:标签适合在没有得到指定名字的人的显式许可下添加。
 
5.5、发送补丁
 
在通过mail发送你的补丁之前,还有其他几个事情需要你小心处理:
 
  * 确认你的邮件发送程序不会破坏这个补丁?那些被邮件客户端工具无缘无故进行空白转换或换行的补丁将无法在另一端适用,并且常常无法被详细地检查。如果在这方面有任何疑问,可以先将补丁邮寄给你自己并确认补丁可以原封不动地展现。
    
   Documentation/email-clients.txt中有一些关于如何使特定的邮件客户端程序适合发送补丁的提示。
 
  * 确认你的补丁中已经没有愚蠢的错误了吗?你应该一直使用scripts/checkpatch.pl检查你的补丁并处理这个脚本提出的各种抱怨。不过请记住,虽然checkpatch.pl是对内核补丁应有的形式进行了大量思考后的体现,但它并不比你更聪明。如果为了修复一个checkpatch.pl的抱怨而使得代码变得更加糟糕,那就不要这么做。
 
补丁应该总是以普通文本形式发送。请不要以附件形式发送补丁;那样将会让评审者在回复中引用补丁部分内容时更加困难。直接将补丁放入邮件消息中即可。
 
在邮件发送补丁时,给那些可能对该补丁感兴趣的人发送一份补丁拷贝是很重要的。与其他一些项目不同,Linux内核项目鼓励大家在发送过多补丁拷贝方面犯错;千万不要假设相关人员会在邮件列表上看到你发布的补丁。尤其是,补丁拷贝应该发送给:
 
  * 受影响的子系统(s)的维护者(们)。前面曾经提到过,MAINTAINTERS文件是寻找这些维护者们的起点。
 
  * 其他曾工作在相同领域的开发者–尤其是那些可能正在此领域工作的人。使用git查看哪些人曾经修改过你正在修改的文件,这样做可能会很有帮助。
 
  * 如果你的补丁应对的是一个bug报告或一个特性请求,也发送一份补丁拷贝给原始问题或请求发起者。
 
  * 发送一份补丁拷贝到相关的邮件列表,如果找不到此类列表,那就发送到linux-kernel邮件列表。
 
  * 如果修复了一个bug,考虑一下该修复是否应该进入到下一个内核稳定版的更新版本中。如果应该进入,你应该给stable@kernel.org发送一份补丁的拷贝。同时也要在补丁内部标签中加入一条:"Cc: stable@kernel.org";这将使得内核稳定版维护小组在你的修复进入主线时收到一个通知。
 
当为一个补丁选择接收者时,最好对谁将最终接受并合并你的补丁做到心中有数。虽然将补丁直接发给Linus Torvalds并让他合并你的补丁是可能的,但事情通常不是这样做的。Linus非常忙,而且有各个子系统的维护者负责监视内核的某个特定部分。通常你将会让那个维护者合并你的补丁。如果没有专门的维护者,Andrew Morton常常作为补丁的最后依赖目标。
 
补丁需要一个好的标题行。补丁标题行的标准格式类似:
 
  [PATCH nn/mm] subsys: one-line description of the patch
 
这里"nn"是补丁的序号,"mm"是这个补丁序列的补丁总数,"subsys"是补丁所影响的子系统的名字。很显然,对于一个单一独立的补丁来说,nn/mm可以被省略的。
 
如果你有一个重要的补丁序列要提交,通常应该先发送一个介绍性的描述作为第零部分。但这个约定并不是被普遍遵循的;如果你使用这种方式,记住介绍部分的信息不会进入到内核的变更日志(changelog)中。因此要保证补丁自身包含完整的变更日志(changelog)信息。
 
通常,一个由多部分组成的补丁的第二以及接下来的部分应该以第一部分的答复(reply)的形式发送,这样他们在接收端才能组合在一起。像git和quilt这样的工具支持群发一批具有适当线索的补丁的命令。但是,如果你的补丁序列很长,且使用git,请使用–no-chain-reply-to命令行选项以避免创建过深的嵌套。
如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats