了解Linux发展史的同学都知道,关于linux吵架史的一段佳话,就是关于内核设计思想之争,这段故事在linus Tovalds的自传中也有提到。我们都知道linux操作系统由Linus Tovalds模仿minix操作系统开发的。
虽然Linux是受MINIX启发而发明,但是在设计思想上采取了和原始UNIX一样的宏内核的设计哲学,而不是MINIX采用的微内核的设计原则。
个人认为Linus Tovalds的伟大之处不在于他发明了Linux,而是他发明了Linux且在自由软件之父Richard Stallman精神的影响下,把Linux开源了,成为开源领域的代表。
在Linux发展之初,林纳斯和安德鲁于1992年在新闻组上有过一场精彩的理念争论。Minix的作者和支持者认为Linux的宏内核构造是“向七十年代的大倒退”,而Linux的支持者认为Minix本身没有实用性。
这场吵架从1992年1月29日, 一直吵到1992年2月10日。帖子的导火索是安德鲁教授发的一个帖子,名字为Linux已经过时了。帖子在1992年2月10日,一个叫尼尔斯的管理员受不了了,然后开了一个新的论坛给linux。从此Minix和Linux,大路朝天,各走一边。 由于当时参与讨论的好多大牛,包括Unix和创始人肯•汤姆森和日后成为Linux内核的二号人物大卫•米勒,还有几个开发BSD内核的人,使这场讨论成为Linux发展史上的佳话。
那究竟什么是微内核的设计原则?什么是宏内核的设计思想?
微内核(Microkernelkernel)
微内核的功能被划分为独立的过程,每个过程叫做一个服务器。理想情况下,只有强烈请求特权服务的服务器才运行在特权模式下,其他服务器都运行在用户空间。不过,所有的服务器都保持独立并运行在各自的地址空间。因此,就不可能像单模块内核那样直接调用函数,而是通过消息传递处理微内核通信:系统采用了进程间通信(IPC)机制,因此,各种服务器之间通过IPC机制互通消息,互换“服务”。服务器的各自独立有效地避免了一个服务器的失效祸及另一个。
同样,模块化的系统允许一个服务器为了另一个服务器而换出。因为IPC机制的开销比函数调用多,又因为会涉及内核空间到用户空间的上下文切换,因此,消息传递需要一定的周期,而宏内核中简单的函数调用没有这些开销。基于此,付之于实际的微内核系统让大部分或全部服务器位于内核,这样,就可以直接调用函数,消除频繁的上下文切换。Windows NT内核和Mach(Mac OS X的组成部分)是微内核的典型实例。不管是Windows NT还是MacOS X,都在其新近版本中不让任何微内核服务器运行在用户空间,这违背了微内核设计的初衷。
在这些设计中,微内核部分经常只但是是个消息转发站:当系统调用模块要给文档系统模块发送消息时,消息直接通过内核转发。这种方式有助于实现模块间的隔离。(某些时候,模块也能够直接给其他模块传递消息。)在一些微内核的设计中,更多的功能,如I/O等,也都被封装在内核中了。但是根本的思想还是要保持微内核尽量小,这样只需要把微内核本身进行移植就能够完成将整个内核移植到新的平台上。其他模块都只依赖于微内核或其他模块,并不直接直接依赖硬件。
微内核设计的一个长处是在不影响系统其他部分的情况下,用更高效的实现代替现有文档系统模块的工作将会更加容易。我们甚至能够在系统运行时将研发出的新系统模块或需要替换现有模块的模块直接而且迅速的加入系统。另外一个长处是无需的模块将不会被加载到内存中,因此微内核就能够更有效的利用内存。
宏内核(Monolithic kernel)
宏内核是两大阵营中一种较为简单的设计,在1980年之前,所有的内核都设计成宏内核。所谓宏内核就是把它从整体上作为一个单独的大过程来实现,并同时运行在一个单独的地址空间。因此,这样的内核通常以单个静态二进制文件的形式存放于磁盘。所有内核服务都在这样的一个大内核空间中运行。内核之间的通信是微不足道的,因为大家都运行在内核态,并身处同一地址空间:内核可以直接调用函数,这与用户空间没有什么区别。这种模式的支持者认为单模块具有简单和高性能的特点。大多数Unix系统都设计为单模块。
宏内核的内部又能够被分为若干模块(或是层次或其他),但是在运行的时候,他是个单独的二进制大映象。其模块间的通讯是通过直接调用其他模块中的函数实现的,而不是消息传递。
宏内核的支持者声称微内核的消息传递开销引起了效率的损失。微内核的支持者则认为因此而增加的内核设计的灵活性和可维护性能够弥补任何损失。
为什么Linux必然是宏内核的呢?一个方面是历史的原因:在Linus的观点看来,通过把内核以单一的方式进行组织并在初始的空间中运行是相当容易的事情。这种决策避免了有关消息传递体系结构,计算模块装载方式等方面的相关工作。(内核模块系统在随后的几年中又进行了不断地改进。)
另外一个原因是充足的研发时间的结果。Linux既没有研发时间的限制,也没有深受市场压力的发行进度。
任何的限制只有并但是分的对内核的修改和扩充。内核的单一设计在内部实现了充分的模块化,在这种条件下的修改或增加都并不怎么困难。而且问题还在于没有必要为了追求尚未证实的可维护性的微小增长而重写Linux的内核。(Linus曾多次特别强调了如下的观点:为了这点利益而损耗速度是不值得的。)
假如Linux是纯微内核设计,那么向其他体系结构上的移植将会比较容易。实际上,有一些微内核,如Mach微内核,就已成功的证实了这种可移植性的长处。实际的情况是,Linux内核的移植虽然不是很简单,但也绝不是不可能的:大约的数字是,向一个全新的体系结构上的典型的移植工作需要30,000到60,000行代码,再加上不到20,000行的驱动程式代码。(并不是任何的移植都需要新的驱动程式代码。)粗略的计算一下,我估计一个典型的移植平均需要50,000行代码。这对于一个程式员或多一个程式小组来说是力所能及的,能够在一年之内完成。虽然这比微内核的移植需要更多的代码,但是Linux的支持者将会提出,这样的Linux内核移植版本比微内核更能够有效的利用底层硬件,因而移植过程中的额外工作是能够从系统性能的提高上得到补偿的。
这种特别设计的权衡也不是很轻松就能够达到的,宏内核的实现策略公然违背了传统的看法,后者认为微内核是未来发展的趋势。但是由于单一模式(大部分情况下)在Linux中运行状态良好,而且内核移植相对来说比较困难,但没有明显地阻碍程式员团体的工作,他们已热情高涨地把内核成功的移植到了现存的大部分实际系统中,更不用说类似掌上型电脑的一些看起来很不实际的目标了。只要Linux的众多特点仍然值得移植,新的移植版本就会不断涌现。
很有趣的一点是,这种争论经常会令人想到前几年CPU领域中RISC和CISC的斗争。现代的成功CPU设计中包含了任何这两种技术,就像linux内核是微内核和单一内核的混合产物相同。Linux内核基本上是单一的,但是他并不是个纯粹的集成内核。
内核模块系统将微内核的许多长处引入到Linux的宏内核设计中。
Linux是一个宏内核,也就是说,Linux内核运行在单独的内核地址空间。不过,Linux汲取了微内核的精华:其引以为豪的是模块化设计、抢占式内核、支持内核线程以及动态装载内核模块的能力。不仅如此,Linux还避其微内核设计上性能损失的缺陷,让所有事情都运行在内核态,直接调用函数,无需消息传递。至今,Linux是模块化的、多线程的以及内核本身可调度的操作系统。实用主义再次占了上风。
当Linus和其他内核开发者设计Linux内核时,他们并没有完全彻底地与Unix诀别。他们充分地认识到,不能忽视Unix的底蕴(特别是Unix的API)。而由于Linux并没有基于某种特定的Unix,Linus和他的伙伴们对每个特定的问题都可以选择已知理想的解决方案——在有些时候,当然也可以创造一些新的方案。以下是对Linux内核与Unix各种变体的内核特点所作的分析比较:
•Linux支持动态加载内核模块。尽管Linux内核也是宏内核,可是允许在需要的时候动态地卸除和加载部分内核代码。
•Linux支持对称多处理(SMP)机制,尽管许多Unix的变体也支持SMP,但传统的Unix并不支持这种机制。
•Linux内核可以抢占(preemptive)。与传统的Unix不同,Linux内核具有允许在内核运行的任务优先执行的能力。在其他各种Unix产品中,只有Solaris和IRIX支持抢占,但是大多数传统的Unix内核不支持抢占。
•Linux对线程支持的实现比较有意思:内核并不区分线程和其他的一般进程。对于内核来说,所有的进程都一样—只不过其中的一些共享资源而已。
•Linux提供具有设备类的面向对象的设备模型、热插拔事件,以及用户空间的设备文件系统(sysfs)。
•Linux忽略了一些被认为是设计得很拙劣的Unix特性,像STREAMS,它还忽略了那些实际上已经根本不会使用的过时标准。
•Linux体现了自由这个词的精髓。
现有的Linux特性集就是Linux公开开发模型自由发展的结果。如果一个特性没有任何价值或者创意很差,没有任何人会被迫去实现它。相反的,在Linux的发展过程中已经形成了一种值得称赞的务实态度:任何改变都要针对现实中确实存在的问题,经过完善的设计并有正确简洁的实现。于是,许多其他现代Unix系统包含的特性,如内核换页机制,都被毫不迟疑的引入进来。
现状
除了QNX和基于Mach的UNIX等个别系统外,几乎全部采用宏内核结构,例如大部分的Unix、Linux,以及Windows(微软声称Windows NT是基于改良的微内核架构的,尽管理论界对此存有异议)。
作为微内核代表的GNU/Hurd的缓慢的发展现状,似乎也在告诉我们微内核的优势是学术理论的结果,而不是从实际应用得出的经验。当然和HURD本身的发展计划及开发模式也有一定关系,事实上以Hurd为代表的微内核的设计思想,其理论上的先进性并没有真正的转化为生产力。
Linux和HURD的现状说明了只有经历市场检验的技术才具有真正的生命力,就像1995年才推出的JAVA语言,因为其顺应了INTERNET编程的需要,现在已经是主流网络编程语言之,诞生于70年代的C语言,现在活力依旧。
Linux的蓬勃发展,似乎说明技术实现上相对简单的操作系统更具有强劲的生命力,而随着Linux不断汲取了微内核的设计思想说明其并没有局限于原有的设计思想,其在实用性层面又一次走在了前面。
对嵌入式物联网感兴趣的小伙伴,可以多了解一下相关信息。(看过来)