Linux Kernel架构赏析

这个文档用来打我前一个文档的脸的:in nek:“优秀架构设计”。既然我前面提出优秀架构不能赏析。我就强行“赏析”一下,看看是真不能赏析还是我多虑了。

Linux Kernel是个成功的架构。因为显而易见,现在Android中,我写本文的电脑中,各种智能机顶盒,特斯拉的车控系统中,各种云服务器中心中(包括微软的Azure)……都使用Linux Kernel。所以,它确实是个“优秀的架构”。我们说优不优秀,不能看它的形态,得看结果。人人都说zircon微内核,低时延,好架构,没有GPL授权问题,马上就要在Android中取代Linux Kernel了……这些……都有可能,但是不是真的“好架构”,这难说得很。我们可以容忍,专业人士也可以判断可能性,但只要没有发生,这上面都有个大大的问号。

我们的服务器,我们认为是很有竞争力的,但拿去客户的机房,人家就一个问题:就算你便宜,你省电,你速度更快,是不是我们把原来的这堆铁箱子淘汰掉,把你的箱子放上来,就可以工作了?我这些换下来的铁箱子可以抵扣部分价钱吗?

你看,先发就有这个优势,后来者就得付出加倍的代价,才能活过来,你觉得你学了别人一切方法就能推翻别人了吗?这是不可能的。你永远都要组合其他要素才能改变态势。更不要说如果你是跟随者,大家都一样投资,你凭什么就能跑得比别人快了?

我在96年左右开始学习Linux,当时操作系统课程学Minix,随着学习Minix自然就会知道有Linux,然后就会有兴趣去安装一下。当时主流的机器刚刚从5/3.5英寸磁盘(容量好像是360k和1.44M?),切换到640M的光驱和几十到数百M的硬盘,这让装个Linux系统有了可能,这个时代,个人电脑开始从DOS切换到Windows 3.1,然后在95年微软搞定了IBM抱以重望的OS/2。推出Windows 95。

在这个时代,Linux就是个爱好者的玩具,能跑起来,但开发人员数量有限,个人电脑开发的大部队都在微软(包括相关生态的比如Borland,Watcom,Raven Software的工程师),有多少在高高在上的Mac我就不知道了。作为生产力工具,我觉得你能用它写个文本文件就不错了,其他的工具,你帮它修Bug的时间比你用来输出的时间还多。

所以,你看这个态势,Linux的架构就是条死路。但它还是有个力量在那里养着它,这个生态其实我不了解,感觉应该就是本来为企业开发的人,学校的人,反正要研究,就总得找个平台,谁最成熟,就是谁了。所以,我觉得Linux在这个阶段能活下来,最成功的架构决策,就是支持PC了。你反正要买PC,Unix没法指望,Windows不让你改,你要讲课,你要研究,你要找个系统玩玩,那就是Linux了。从Linus的Just for fun里面说到的心路历程,这个时间他自己就是要玩,所以就是大家一起玩。这个平台的目的性就非常强,就是很容易装,很容易改,其他都是细节。养活它的是爱好者(包括研究者,这是爱好者的重要组成部分),它的总架构师的思路是“我也喜欢玩。不好玩的,阻碍我玩的,都别合进来”。这样一个“目标”,和这个目标和能养活它的人群一契合,它无法打败Windows,但它确实填补的它的目标市场,它就能活。所谓“弱小不是生存的障碍,傲慢才是”,就是这个意思。你明明不具备打倒Windows的基础,非要向这个角度挺进,就是死路,但Windows在“研究者”这个市场上,也是没有任何竞争力的,你填补这个市场,就能活下来。至于服务器这个市场,完全就是Unix的天下,Windows都摸不着边,就更不用说了。

这中间,GNU的支持也是个重要的控制要素,但不改变我们的主逻辑链,这里就不深入讨论了。

这个阶段其实Linux是有各种BSD的挑战的,我觉得其实也没有谁胜过谁一说。但总的来说,还是用Linux的人比较多。我觉得核心原因也和Linus纯粹为了好玩,没有什么“理想”有关系的,很多BSD系统都有一群专家在控制,有很多想法,要求,一定要秉承什么什么理念,架构设想,很多需求都收不进去,这样,不是圈内人都进不去。Linus这个人就比较开放,只要好玩,什么狗屁微内核,分层,C++,封装,他是一概看不上的,这样,陪他一起玩的人反而多。但他又不是那种允许你随便破坏他架构的人。这从他有一个会议上的观点可以看出来:他认为,大部分模块间的关系,只要确定了数据结构的关系,这个模块的关系就确定了。这一点在git的设计上表现得淋漓尽致。

但这并非Linus的唯一架构理念,他的架构理念其实是不容易描述清楚的,但如果你持续看他的邮件,你还是知道他是有规律的,只是这些规律不能用一两句话总结而已。很多人觉得Linus喜欢骂人,但很多人可能不知道,很多人喜欢Linus骂人(比如我),因为他骂完以后——虽然不总是——你常常觉得这个观点还挺对的。

但无论如何吧,在这个时代,Linux就是一个研究和学习的系统,对商业是没有冲击的,其中很重要的一个要素是Linux基本上是个单核系统,多核怎么做,基本上开发者都是不知道的。那时我看的很多资料,包括我自己在公司里刚开始研究怎么做多核,很多高端专家研讨,还在讨论应该用多核还是应该用多CPU,应该用内存做核间同步还是靠IPC来做核间同步。这样的问题现在随随便便很多工程师都可以教这些专家做人,但当时,真没有几个人能确定(因为这还和工艺和生态有关)。当时的Linux的内核就是一个大锁,进去就锁上,里面就是一个单线索的大程序,这个最基本的设计,降低了研究问题的难度,如果你学习操作系统,这种系统特别好研究,但你这没法有商业竞争力。

这个阶段IBM进来了,背景我不太记得了,大概的情况应该是IBM在Wintel联盟的攻击下,丢掉了很多低端市场,Wintel服务器稳定性开始提高,蚕食掉了原来用Unix的服务器的低端份额。IBM受不了了,就开始在自己的低端服务器上引入Linux。但Linux内核这个结构根本没有竞争力。所以IBM派了很多人进来帮忙修补这个内核,其中我记得一个非常重要的修改是引入了RCU锁,这个解开了很多性能瓶颈问题。我当时在我们公司内负责部分网络设备多核改造的升级工作,我就是看懂了RCU的设计,才正经明白多核到底是怎么回事的。由此推想,也许很多业界从业人员也是从这里开始确切去了解这个多核的代码是怎么写的吧。现在我们当然觉得写多核的代码也就那样,但那个时候其实并非如此。

越过多核这个坎后,Linux在低端服务器领域就有一定地位了,特别是比较成熟的LAMP方案,几乎每个人都会用的。这个阶段其实有个比较长的拉锯时间,当时我正好到印度那边去做下一代网络平台开发,那个点刚建立,他们顺便要我做那个站点的系统管理员。我一开始用的就是LAMP和Sendmail来建那边的IT系统的,因为这个除了需要买几台服务器,没有任何软件成本。但这个消耗我太多的精力了,动不动就要改脚本,甚至重新编译程序。后来我就换成微软的Backoffice,这个东西的Bug一点都不少,但每次出问题了也不是我的错,打电话去骂微软的维护就可以了。至于买Backoffice的费用,对一家大公司来说,那就不算钱。这个时代,Linux开始积累,成熟,抛开了和其他“爱好者系统”的距离,但并没有成为一个不可撼动的力量。

但随着之后云计算的兴起,这个问题就彻底改观了。云数据中心一把就有数千个节点,你让他给每个版本买商业授权,这完全是开玩笑。而且这些管理员又不像我当时那样,只有一个兼职的开发者。他们有整一个团队,有需要就改,一点问题没有。一眼扫过去,整个可选范围中,能符合要求的系统除了Linux没有别人,Linux又恰恰是来自服务器领域的设计(基于Unix标准的设计),应用一旦展开,就没有人可以阻挡它了。在服务器市场成熟,当Android这样的系统要选底层的时候,Linux几乎就是独一无二的选择。你可以说Android的架构是可以使用其他OS的,但偏偏就是没有人选,你说这个控制要素是什么?——用多了就是一切啊。

那我们又要回来看扩大以后的内斗问题了,Linux开源的,谁不想大家的代码合到我的版本上?这样比如我做CPU的,我负责适配Linux到我的CPU,你负责把你的数据库直接mmap的内存做到我的平台上,做IOMMU的人负责把日志内存映射到NVMEM上,虚拟化的人负责把IOMMU的两层翻译映射为虚拟化的解决方案上。这样Linux就成了我的私家禁地了。支持我的CPU特别好,别人的CPU都不好。有系统这样维护的,比如iOS。

但对于Linux,大家还是屁颠屁颠把代码合到Linus手中的版本上?为什么?

首先,我觉得还是那个问题:因为这样没出问题。这还是前面说的,这是“先发优势”。Linus从没有使人失望。但其他人的分支——最后总让人失望。

做过大团队管理的人都应该知道,就算你想公平,你也没有让人公平的信息。每两个月推十万个Patch到你面前,你Linus八臂拿吒都不好使,你怎么保证“公平”?我们一直在lkml上看Linus的发言的话,我觉得他的策略大体是这样的:自己在行的部分,他会进来参与具体的技术讨论,不在行的就不理,但无论你最后变成啥样了,他可以在PC上玩的那个基础是不变的。他作为一个用户,按他的设想去总体上去“用”这个系统,这一点不符合要求的时候,他就会去细看他关心的一部分代码,这样,别人要来占便宜,都可以占,他不拦任何人,但如果你影响了我的范围,那就要吵一把了。这样,也许是他长进了,了解了你这个地方的细节,也许是你就不对,被他K回去了。这样一个过程会保证这个系统在逻辑上是有规律的,同时也不会影响这棵树的“长大”。

随着这么一个控制过程,Linux现在的代码基本上模块和模块互相之间还是相对独立的,但它的原始基因还是那个“Just For Fun”的那个核。即使今天Linus对ARM服务器的建议还是这个:做好PC,没有PC就没有服务器。这背后就是这个东西必须能在开发者手上“把玩”这个要求。所以Linux对开发者的友好程度仍是无与伦比的。这一点本身就保证了其他领域的改进是有序的,这就给了这些领域一个可控的机会:如果搭这些领域没有搭到足够的高度,我们可以退回来,再搭一次。当然,Linux中的maintainer选得都相当靠谱,这种情况非常少,我觉得达成这一点,和Linus不打哈哈,有问题直接骂人,没有人用情面来做设计判断,是很有关系的。不要觉得开源就能成功,能达到Linux Kernel这么成功的开源社区,很少很少的。更不要觉得GPL就能保证不分裂,直接和版本到Redhat的那个内核中,理解就可以使用了,为什么不合到那边去?

如果要为这个架构行为提取一个成功的Pattern的话,我想也许就是简单的“不改初心”。一把刀,总是按一个角度磨利了,然后挑领域,才会保持竞争力,如果一时要打锤子,一时要磨镰刀,这个东西就不会有竞争力了。

等到遇到环境彻底变化了,刀子没有用了,这也只能接受了。到老方知非力取,既然选择了刀子,就只能当好一把刀子。

Linux很多时候不是不会遇到这种环境变化的,比如我们都用Linux的协议栈,协议栈都在内核。但DPDK就把这个东西移出内核了,如果未来这个东西很成功(其实暂时看可能性不大),Linux就失去这部分的市场(广义的市场,指用户群体),一个一个领域不需要这样的市场了,整个市场就没有了,Linux就死了。

又比如Linux的调度器,无论如何是不会适合实时应用的,它也不反对你进行实时性改进,但Linus还是首先校验你最终的PC上的效果,这会阻碍很多实时补丁的合入。但还是那句话,你是一把刀子,首先必须像刀子一样锋利再说,至于还可以用来开汽水——能开当然好,不是第一位的。

很多变化要素还可以来得非常微妙,比如现在不少Linux发行版其实都不好活了。我们想想,过去你为什么要用一个发行版?很大程度上,是因为这些发行版可以和很多硬件厂家适配。用户买了以后不会绑死在一个供应商上。但现在云运营商一次采购一大批服务器,而且内核都要自己定义的,这个优势就没有了,发行版供应商的生存条件没有了,它就没有了。甚至只要钱少了,再投很大的代价就很困难了,可能这个投入就会被整体切掉,只剩下CPU和整机提供商投入这方面的发展了。

说起来,我这个推演,一定程度上证明了还是有些经典架构可以赏析的。但另一方面也同时证明的前面那个“优秀架构没有什么东西可赏析的”。这个地方的在于你的预期是什么。是你指望赏析以后学到点方法呢?还是指望赏析一下然后感叹“世事无常”呢?

关键在于,这种架构策略是建立在你每个具体设计基本都是靠谱的基础上的,你专门学个“Just For Fun”的样子,定义个接口把内部的变化都暴露在接口上,今天整改个代码对齐,明天弄个中断升级……要不“情商高”,什么狗屁需求都敢接受,要不冷清高,非要坚持什么分层理念,那你门都没有摸着,谈什么架构策略不策略的,胡说八道而已。策略是用千百万个比如这样的具体的战术组成的:in nek:所谓内部设计,每个都有大量的细节,不是你提出取出的这个表面的高层Pattern。

编辑于 05-31

文章被以下专栏收录