【生意多】-免费发布分类信息
当前位置: 首页 » 新闻 » 教程 » 正文

如何参与到 Linux 社区中来(中)

放大字体  缩小字体 发布日期:2020-06-06 23:20:03    浏览次数:15
导读

  从前面谈到的内核开发中,我们可以得知整个内核的开发过程是取决于将来自四面八方的补丁有效整合的能力。如果没有合适的强大的工具支撑,这整个项目的协作恐怕就是空谈。关于如何使用这些工具的教程远远超出了本文档的范围,这里仅仅提供一些指导性的内容。  到目前为止,内核社区使用的主要源代码管理系统是 git。Gi

  从前面谈到的内核开发中,我们可以得知整个内核的开发过程是取决于将来自四面八方的补丁有效整合的能力。如果没有合适的强大的工具支撑,这整个项目的协作恐怕就是空谈。关于如何使用这些工具的教程远远超出了本文档的范围,这里仅仅提供一些指导性的内容。

  到目前为止,内核社区使用的主要源代码管理系统是 git。Git 是自由软件社区中开发的众多分布式版本控制系统之一。它非常适用于内核的开发,因为它在处理大型存储库和大量补丁时表现卓越。它也因难以学习和使用而闻名,尽管随着时间的推移它已经变得非常不错了。对于内核开发来说,掌握git的使用是必备技能,因为即使开发者不使用它来进行日常的内核开发,最后也要面临和其他开发人员的同步问题以及合并到主干等。

  Git 现在已经整合到所有的Linux发行版当中了,其官方站点:。该网站有详尽的文档和教程,另外,关于针对Linux内核特定的Git知识可以参考:。在不使用git的内核开发人员中,最受欢迎的选择几乎可以肯定是Mercurial:,Mercurial 和 Git 有很多相似的特性,但是它在界面上使用更加的方便。

  另外一个值得推荐的工具是Quilt:。Quilt 是一款补丁管理系统,而并非源代码管理系统,它并不会追踪所有的历史内容。相反,它是针对不断发展的代码库跟踪一组特定的更改。一些主要的子系统的维护者使用 Quilt 来管理提交到上游的补丁的,对于特定的tree来说,(如 -mm)Quilt可以高效的完成任务。

  大量的Linux内核开发工作都是通过邮件列表来完成的。如果说哪位开发者没有加入任何的邮件列表,那么ta一定对于社区成员的理解还差了些。当然,邮件列表也不是十全十美的工具,至少它有这样两个弊端:大量的邮件信息把开发者吞噬掉;或者是违反了某些约定,有时候甚至二者都会有。

  内核开发的核心邮件列表当然是linux-kernel。没见过世面的看到该列表,一定会被惊到,它每天的可以达到500封以上的邮件,大多数是技术的细节,正因为如此,所以讨论的参与者们并不介意诸如礼貌之类的事情。但是没有其他地方可以将内核开发社区整体结合在一起;不订阅此列表的开发人员将错过很多重要的信息。

  不要试图去关注所有的话题 ———— 没有人能做到。重要的是过滤所关注的主题(尽管请注意长时间运行的对话可能会偏离原始主题而不更改电子邮件主题行)和参与的人。

  当响应linux-kernel电子邮件(或其他列表上的电子邮件)时,保留所有涉及的Cc:所有参与者的。在没有强烈理由(例如显式请求)的情况下,永远不要去删除任何的收件人。始终确保回复的人员在抄送列表中。此约定还使得无需明确要求复制对帖子的回复。

  在提问之前,请先搜索邮件列表归档(以及Google网络)。一些开发人员可能会对那些显然没有完成作业的人感到不耐烦。

  要避免置顶情形(将自己的回答置于正在回复的引用文本之上的做法)。这么做会让人难以阅读,也会给人留下非常不好的印象。

  关于如何开始内核开发过程的问题是很常见的,发起问题的有个人也有公司。但是人们往往也并没有耐心等待他人的回答,就开始干了起来,这就导致更为严重的后果,还不如刚开始什么都不知道的好。

  企业常见的做法是找一些知名的开发人员来启动开发团队。而事实上,这也是非常有效的一种方式。但是,这往往也是最为昂贵的一种做法,而且对于增加内核开发人员没有直接的效应。企业的另外一种考虑是,增加一些时间的投入,让内部现有的开发人员参与到Linux内核的开发当中来,从长远来看,这份投入是值得的,不仅可以培养出一些深入了解内核的开发人员,要知道这些人还会进而帮助和影响乃至培训更多的人。从中长期来说,这样的做法是最为划算的。

  而对于个人开发者而言,往往在从何处入手而踌躇不前,这是完全可以理解的。从一个巨大规模的项目开始,是令人心生畏惧的,不过我们可以从一些小处着手来试着搞定。比如一个蛮不错的起点就是去修复他人的拼写错误或者是不怎么重要的代码风格问题,不过需要提前向你声明的是:这样的补丁会产生一定程度的噪音,这对整个开发社区来说会分散注意力,因此,它们越来越被人们所瞧不起。所以,以这样的方式来开启自己的内核开发之旅,并不能获得他人足够的认可。

  对于所有内核初学者来说,首要完成的工作时:“确保内核在所有可以完成任务的机器上始终完美运行”。通常这样做的方法是与其他人一起解决问题(这可能需要持久性!)但这很好 - 它是内核开发的一部分。

  在没有明显问题要解决的情况下,建议开发人员查看当前的回归列表和优先级一般的漏洞。要知道从来就没有什么短期而紧急的问题;通过解决这些问题,开发人员将获得该过程的经验,同时与开发社区的其他人建立尊重。

  在想象 Linux 内核开发项目的时候,人们可能会以为是直接就开始编码的。事实上不是这样的,Linux 内核作为软件项目和其它的项目没有什么差别,即在开始编写第一行代码之前要进行充足的准备工作,而这是所有软件项目成功的基础条件。在早期规划和沟通上花一些时间,会让以后的路更容易走,可以节省更多的时间。

  和任何工程项目一样,Kernel 的成功,是因为其对于要解决的问题描述非常的清晰。在某种情况下,这点非常容易做到:例如,当需要特定硬件的驱动程序时;但是更多的时候,实际的问题和众人所描述的相差十万八千里,而这往往会导致更多的困难。

  举一个多年以前的例子:Linux 音频的开发人员寻求一种运行应用程序的方法,而不会因系统中的过度延迟而导致丢失或其他内容。他们最初采取的解决方案是将音频的内核模块和Linux安全模块(LSM)之间做一个hook,并将此模块配置为授予特定应用程序访问实时调度程序的权限。当完成了该模块的编写之后,发送到了 linux-kernel 邮件列表,没过多久就遇到了问题。

  对于音频开发者而言,目前的安全模块足以解决他们的问题,但是,对于更广泛的内核社区来说,它被视为滥用LSM框架(它不是为了将特权授予他们原本不会拥有的进程)以及系统稳定性的风险。内核社区认为的首选解决方案应该是短期内通过限制机制进行的实时调度访问,以及长期持续的延迟减少工作。

  然而,音频的开发者并没有去检查他们已经实现的内容,他们也不愿意接受替代的方案;由此产生的分歧使得开发人员对整个内核开发过程感到失望;其中一个在音频的邮件列表中发布了如下内容:

  有许多非常优秀的Linux内核开发人员,但他们往往会被一大群傲慢的傻瓜吓跑。向这些人传达用户的需求简直是在浪费时间。他们过于自命不凡,而根本什么都听不进去。

  而实际上完全不是这么回事,内核开发人员更关注系统稳定性,长期维护以及找到问题的正确解决方案,而不是针对特定模块的特定解决办法。这个故事的寓意在于要去关注问题本身—— 而不是特定的解决办法—— 而且要在实际投入代码工作之前,尽可能多的去和开发社区进行充分的讨论。

  在规划内核开发项目时,在启动实现之前与社区进行讨论是非常有意义的。早期沟通可以通过多种方式节省时间和麻烦:

  很有可能是目前内核的解决方式是开发者还没有理解,Linux 内核是一个非常大的项目,拥有非常多的功能和特性,而且它们往往并不是那么的明显,另外,并不是所有的功能都能文档化,而且还特别容易错过一些具体的功能,比如一位开发者看到一个发布的完整的设备驱动程序,该程序和现有的驱动程序重复了,而新的作者完全没有意识到。重新发明现有车轮的代码不仅浪费;它也不会被主干所接受。

  可能存在所提出的解决方案对于主干合是不可接受的因素。在编写代码之前最好找出这样的潜在问题。

  其他开发人员完全有可能考虑过这个问题;他们可能有更好的解决方案的想法,并可能愿意帮助创建该方案。

  内核发展多年以来,总结出一个非常有意义的教训:内核的代码是在封闭的情况下设计和实现的话,总是存在各种各样的问题,而且这些问题总是在发布到社区之后才能被发现。而且有的时候更改为严重,这些实现需要花费数月乃至数年的时间才能达到社区的标准。这里列举几个例子:

  Devicescape网络堆栈是为单处理器系统设计和实现的。在它适用于多处理器系统之前,它无法合并到内核的主干当中,将锁定等改造成代码是一项艰巨的任务;因此,此代码(现在称为mac80211)的合并延迟了一年多。

  Reiser4 文件系统,自身包含了许多功能,这些功能在核心内核开发人员看来,很多已经在虚拟文件系统层中实现了,它还包括在不将系统暴露给用户导致的死锁的情况下无法轻松实现的功能。这些问题本身已经说明,更不用说开发者拒绝解决其中的一些问题,这明显导致 Reiser4 远离了主干。

  AppArmor 安全模块,被认为采用了不安全和不可靠的方式使用内部虚拟文件系统的数据结构。尽管后来代码进行了大幅的修改,但是离主干依旧很远。

  以上所有这些案例,都以惨痛的代价告诉我们,要尽早的去和其他的内核开发人员进行充分的沟通和讨论,可以节省大量的时间,可以避免那些让人抓狂的痛苦经历。

  当开发者决定将其所规划的内容公布时,接下来要做的事情就是:从哪里开始?答案其实蛮简单:找到对的邮件列表,以及对的维护者。对于邮件列表来说,就是我们在前面也提及的:最好的方法到 MAINTAINERS 文件中查找。如果在该文件中有相应的子系统列表的话,就直接到该地址去发邮件即可,这要胜过跑到 linux-kernel 主列表发送;因为在相应的子系统中有更大机会接触到相关的开发人员。

  找到维护者确实是有点困难,重要的事情说三遍,MAINTAINERS 文件是个不错的开始。尽管该文件有的时候,并不能做到及时的更新,甚至有时候还可能发生有的子系统根本就没有在这里被提及。更有甚者,MAINTAINERS 所列出的人,可能早已不在当前担任任何的角色了。因此,当对于联系谁有疑问时,一个有用的技巧就是使用 git(特别是git log) 来查看当前的活跃情况,该命令可以看到是谁撰写的补丁,以及谁(如果有的话)将签名附加在补丁上。这些人才是最适合帮助开发新的项目的开发者。

  如果你试过了所有的方法,还是无法找到对应的维护者,那么你就去找一下 Andrew Morton,和他聊聊,这也是追踪特定代码片段维护者的有效方法之一。

  一害。在规划中描述正在解决的问题以及打算如何实现等等,换句话说,开发者提供的任何信息都可以帮助到开发社区。

  其实,事情可能出乎大家的意料,在这个阶段也就是在开发者公开了自己的规划之时,令人沮丧的可能不是有人反对,而是很少甚至根本就没有人理会。这样惨烈的局面的造成可能的原因有:

  如果请求评论发布几乎没有产生评论,请不要认为这就意味着人们对项目没有兴趣。当然,你也不能想当然的以为,你的规划是没有问题的。如果发生这样的情况,最好的办法是继续追踪,保持和社区的紧密联系。

  如果开发者的工作是在自己公司里的环境中完成的,(当然,大多数Linux内核的工作都是这样),显而易见,有一项重要的工作需要去做,那就是将公司的代码发布到公开邮件列表之前,要获得所在公司的许可。在GPL兼容许可下发布尚未清除的代码可能会造成问题;公司的管理层和法律人员越早就内核开发项目的发布达成一致意见,那么对于每个人都是有益处的。

  一些读者可能正在考虑将他们在内核的工作去支持尚未得到官方认可的产品中。在公共邮件列表上公布其雇主的计划可能不是一个好的办法。当发生这样的情况时,笔者的建议是去为公司保密。这不是那种我们通常意义上说的闭门造车,要注意它们之间的本质区别。

  当然,也有一些公司在开发早期就透漏了自己的计划,没法做到封闭,那么拥有经验丰富的内核开发人员的公司就会选择以开放的方式来发展,因为他们预见到了集成的问题会更加的严重。对于没有这种内部专业知识的公司,最好的选择是聘请外部开发人员,进而根据保密协议去审查计划。Linux 基金会有一个 NDA 计划,旨在专门帮助公司解决这种情况;更多信息可在以下网址找到:

  虽然对于一个可靠的、面向社区的设计过程有很多要说的,但是最终要证明事实的仍然是代码本身,这里所说的代码是指那些要由其他开发人员检查并合并(或者不合并)到主干的代码,因此,这些代码至关重要,它直接决定着项目的成功与否。

  本节将为大家讲解关于编码的流程。首先,我们来看看内核开发人员经常出错的环节,然后将聚焦于转向正确的事情以及可以帮助完成任务的工具。

  Linux 内核一直以来都有可以说是相当标准的代码风格,具体描述在内核文档 documentation/CodingStyle。但是,在绝大多数时候,这份文档更像是一份指南,而不是必须执行。那现实的情况就是,内核中存在大量不符合编码风格准则的代码。该代码的存在会给内核开发人员带来两种不祥的兆头。

  首先就是那些认为内核的编码标准不再重要的人们,他们也不认为没有必要强制执行。然而事实上,如果这些人的代码没有按照标准去编码,那么在合并到主干的过程中就会遭遇重重困难,根据过去的观察,那些开始的时候不注意标准的人都经历了此类重新调整格式的过程。像Linux内核这样巨大无比的项目,代码是需要一些一致性要求的,这样能够使得开发者快速的理解任何部分成为可能,而不是把精力耗费在理解各种稀奇古怪的“混乱风格”。

  当然,有的时候会发生内核的编码风格和开发人员所在公司要求的编码习惯发生冲突,这个时候,想要合并到主干仓库的话,公司就需要作出妥协。将代码贡献到上游内核,其实就意味着公司就必须放弃一些诸如控制权之类的 ———— 当然其中会包括代码采用何种的风格。

  另外一个常见的陷阱是,会主观的以为当下的内核中已经存在的代码存在风格问题,需要进行修复,开发人员可能会开始生成重新格式化补丁,以此来熟悉流程,或者将其名称添加到内核更改日志中,或者两者兼而有之。但纯粹的编码风格修复会被开发社区视为噪音;这样的做法往往会得到一个冰冷的漠视。在处理功能性代码时顺带修复一下代码样式是很自然的过程,但编码样式的更改不应该提到和功能性一样的等级。

  编码风格的文档也不应被视为永远不能违反的绝对法律。如果有充分的理由反对默认风格(例如,如果分割成适合80列限制,那么这条线的可读性会大大降低),就大胆的去做吧。

  计算机科学的教授们,在为学生们讲课的时候,告诉大家要尽可能的去使用抽象,好处是灵活性更强,且信息还能隐藏,当然,Linux 内核也在大量的使用抽象,如此量级的代码,不使用抽象是不敢想象的,但经验表明,过度或过早的抽象可能与过早优化一样有害。抽象应该用于所需的水平,过犹不及。

  在一个简单的层面上,考虑一个函数,该函数的参数总是被所有调用者传递为零。人们可以保留这个观点,以防有人最终需要使用它提供的额外灵活性。但是到那个时候,实现这个额外参数的代码已经被一些从未被注意到的微妙方式打破了 - 因为它从未被使用过。退一步讲,当需要额外的灵活性时,它不会以符合程序员早期期望的方式那样做的。内核开发人员会定期提交补丁以删除未使用的参数;一般来说,它们本来就不应该被预设式的添加。

  隐藏访问硬件的抽象层 ———经常允许大量的驱动程序与多个操作一起使用——— 这是经常让人头痛的事情。这些层会使代码模糊不清,并可能造成性能损失;它们不应该属于Linux内核。

  另一方面,如果您发现自己从另一个内核子系统复制了大量代码,现在是时候问一下,将一些代码提取到一个单独的库中或者在更高级别实现该功能,是否更有意义?在整个内核中复制相同的代码没有任何价值。

  C 语言的预处理器强大的功能,让一些C程序员欲罢不能,他们认为它是一种有效地将大量灵活性编码到源文件中的方法。但是预处理器毕竟不是C 语言本身,大量使用预处理器会导致代码难以阅读,也不容易让编译器检查出问题所在。过多的使用预处理器的代码是要进行重构的。

  使用#ifdef进行条件编译确实是一个强大的功能,内核也经常会使用到它,但是,几乎很少有人愿意看到代码是被ifdef所覆盖的。所以,内核团队一般的规则是,尽量将使用ifdef的范围局限在头文件中,有条件地编译的代码可以被限制在函数中,如果代码不存在,则这些函数为空。然后,编译器将静默地优化对空函数的调用。这样的话,就会拥有更加清晰的代码,也更容易去遵循。

  C预处理器宏存在许多危险,包括可能对具有副作用且无类型安全性的表达式进行多重评估。如果你想要定义宏,还是先考虑一下改为创建内联函数。效果是一样的,但是内联函数更加容易阅读,也不会出现多次评估参数的情况,而且还允许编译器对参数和返回值执行类型检查。

  使用函数调用,而是使用内联函数来填充源文件,目的是为了更快的完成工作。但是,这么做会影响到性能。由于这些代码会在每次函数调用都会被复制一次,到最后会让编译后的内核变得非常大。反过来,这会对处理器的内存缓存造成压力,这会大大降低执行速度。基于此,内联函数应该非常的小,而且不鼓励经常使用,毕竟,函数调用的成本并不高;大量内联函数的创建是过早优化的典型例子。

  通常情况下,内核开发者会忽略缓存效应的危险。过去在数据结构课程当中讲授的经典时间/空间权衡,在当代硬件的设施中已经不再适用。空间即时间,怎么说一个较大的程序都要慢于紧凑的程序。

  在2006年5月,”Devicescape” 网络栈非常高调的准备好进入主干,基于GPL协议,这次捐赠对于社区是非常受欢迎的,因为Linux向来对于无线网络的支持不够尽善尽美,而且 Devicescape 完全可以弥补这些,然而,直到2007年6月,这段代码才线)。这中间到底发生了什么?

  Devicescape 的代码有着浓重的基于封闭式的开发方式的痕迹,其中一个尤其重大的问题是它并没有支持多处理系统,在此网络栈(现在称为 mac80211)可以合并到主干之前,需要将锁定方案修改以支持多处理器。

  曾几何时,Linux 内核代码的开发是不需要考虑多处理器所要求的并发问题的,然而,现在,这份文件是在双核笔记本电脑上编写的。即使在单处理器系统上,提高响应能力的工作也会提高内核中的并发性。所以,那些毋需考虑锁的编码日子一去不复返了。

  任何可由多个线程同时访问的资源(数据结构,硬件寄存器等)必须由锁保护。现在编写代码考虑锁是默认的做法,尽管改变是一件蛮困难的事情。内核开发人员应该花时间了解可用的锁定原语,以便为工作选择合适的工具。目前而言,缺乏对并发性的关注的代码将难以进入主干。

  值得一提的最后一个危险是:它可能很容易做出改变(这可能会带来很大的改进),这会导致现有用户无法使用。这种变化被称为“回归”,回归在主干内核中变得最不受欢迎。除少数例外情况外,如果无法及时修复回归,则会退回导致回归的更改。最好要避免回归的问题。

  人们经常认为,如果一个回归可以让事情对更多的人有用,而只带来少数的问题,那么回归就是合理的。为什么在能为十个系统带来新的功能而只有一个系统崩溃做出改进了呢?Linus在2007年7月表达了对这个问题的最佳答案:

  我们不会通过引入新问题来修复错误。这样的方式是疯子行为,因为没有人知道你是否真的取得了任何真正的进行。它是两步前进,后退一步,还是前进一步又后退两步?

  一种特别不受欢迎的回归类型是用户空间ABI的任何类型的变化。将接口导出到用户空间后,必须无限期地支持它。这一事实使得用户空间接口的创建特别具有挑战性:因为它们不能以不相容的方式改变,所以必须在第一时间完成。因此,始终需要大量的深思熟虑、清晰的说明以及对用户空间接口的大量审核。

 
关键词: linux人社区
(文/小编)
打赏
免责声明
• 
本文为小编原创作品,作者: 小编。欢迎转载,转载请注明原文出处:http://www.31duo.com/news/show-245470.html 。本文仅代表作者个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,作者需自行承担相应责任。涉及到版权或其他问题,请及时联系我们。
 

(c)2016-2019 31DUO.COM All Rights Reserved浙ICP备19001410号-4

浙ICP备19001410号-4