不知怎么的,最近“微内核 vs 宏内核”又成了热门话题。这场争论从 1992 年开始……

我很久没有关心操作系统了,因为通常所谓的“操作系统”,在我心里不过是一个 C 语言的运行时系统,就像 JVM 是 Java 的运行时系统一样。由于 C 语言的缺陷,这些系统引入了各种无需有的概念以及它们带来的复杂性和开销:进程,线程,虚拟地址…… 微内核与宏内核之争当然也包括在内。
在我的理念里,一个优秀的操作系统本应该是这个样子,简单的很。
跟很多人聊操作系统是一件闹心的事,因为我往往会故意抛弃一些术语和概念,从零开始讨论。我试图从“计算本质”的出发点来理解这类事物,理解它们的起因,发展,现状和可能的改进。我所关心的往往是“这个事物应该是什么样子”,“还可以是什么样子”,而不只是“它现在是什么样子”。不明白我的这一特性,又自恃懂点东西的人,往往会误以为我连基本的术语都不明白。天就这样被他们聊死了。
幸运的是我有几个聊得来的朋友,他们不会那么教条主义。于是今天我跟一个朋友在微信上聊起了“微内核 vs 宏内核”这件事。其实这个问题在我脑子里已经比较清楚了,可是通过这些对话,我发现学到了新的东西。这些东西是我们两个人在对话之前可能都没有完全理解的,也许很多其他人也没有理解。所以我觉得可以把这些有价值的对话记录下来。
我不想从头解释这件事情,因为你可以从网络上找到微内核和宏内核的设计原理。我想展示在这里的只是我们的对话,里面有对也有错。对话是一个很有意思的东西,我觉得比平铺直叙的文章还要有效一些。
好了,现在开始。对话人物“IAN”是我,“LD”是我的一个朋友。
(8 月 19 日,开始)
IAN:好多年没折腾 OS,现在再折腾应该有新的发现。这篇 paper 说 Minix 3 比 Linux 要慢 510%。通常的定义,说微内核只需要 send 和 receive 两个系统调用。你不觉得有问题吗?其实函数调用的本质就是 send 和 receive,但只有两个系统调用,这种做法是过度的复用(multiplex)。
LD:是。
(下载 Minix 3 源代码看了一会儿。上网搜索关于微内核的资料……)
IAN:微内核似乎一直没解决性能问题。后面的 L4, QNX… 把 sever 隔离在不同的地址空间似乎是个最大的问题。
LD:导致通讯成本特别大。本来传递个地址就可以的事。现在要整个复制过去。
IAN:地址空间不应该分开。或者也许可以在 MMU 上面做文章,传递时把那片内存给 map 过去。这样上下文切换又是一个开销…… 函数调用被搞的这么麻烦,微内核似乎确实是不行。对了,微内核服务调用时会产生进程切换吗?
LD:会,按照微内核的定义,每一个基本单元都是一个进程。
IAN:完蛋了。
LD:内存管理是一个进程,IO 管理是一个进程,每个设备驱动是一个进程,中断管理是一个进程。
IAN:进程切换的开销……
LD:为了降低进程间通信开销,所以定义了 L4。我也不太懂这个有啥用。
IAN:改善的是通信开销,但仍然有进程切换开销。我刚看了一下 L4,它是从寄存器传值,但是进程切换会把寄存器都放到内存吧。
LD:一个外设产生了中断,中断管理进程接收到到中断,发一个消息给相应的设备驱动进程,这个进程处理中断请求,如果设备驱动有 bug,挂了,也不会干扰 OS。这就是微内核逻辑。
LD:对呀,所以 L4 意义似乎不大。
LD:带“微”的除了微软和微信,没一个成功的。
LD:最近流行的所谓微服务。
IAN:驱动的 bug 应该有其他办法。
LD:现在的 OS 的问题,就是内核微小的错误,都是让整个系统挂掉。这和我们写软件应该用多进程还是多线程。同样的问题。
IAN:应该从硬件底层彻底抛弃现在的进程切换方式。保存的上下文太多。
LD:现在 OS 不是分成 user 和 kernel 保护级别么。 我觉得再增加一个两个保护级别,专门针对设备驱动程序似乎是更好的选择。
IAN:我以前设想一个办法可以完全不需要保护级别。而且不需要虚拟内存。
LD:怎么办? 编译器静态分析搞定?Rust?
IAN:完全使用实地址,但是代码无法访问对象外面的内存。
LD:靠编译器保证?
IAN:不需要多先进的编译器。语言里面没有指针这东西就行,这样你没法访问不是给你的对象。嗯,需要抛弃 C 语言……
LD:Rust!
IAN:其实 JVM 早就是那样了。只不过通常不认为它是一个操作系统,但操作系统完全可以做成那样。
LD:所谓对象,就是每次地址访问,除了地址还有一个 size? 超过 size 不允许?还是编译器确保一定不会超过 size?
IAN:你在 Java 或者其它高级语言比如 Python… 都没法访问对象外面的内存啊。只有 C 可以,因为 C 有指针,可以随便指到哪。
LD:是的。C 这种方式,就是天天在没有护栏的桥上走来走去。除了越界访问,还有一个问题,就是多个 task 同时改一块内存。
IAN:然后为了防止越界,有了“进程”,“虚拟地址”这种概念。
LD:虚拟地址,还是为了用虚拟内存。
IAN:虚拟地址,虚拟内存就是为了隔离。每个进程都以为地址从0开始,然后本来很容易的函数调用被隔离开了。如果改变了这个,微内核就真的可以很快了。实际上内核就不存在了…… 哦,还是有。就只剩下调度器,内存管理。IPC 没了,被函数调用所取代。
LD:硬件级别 callcc。
IAN:也没有 callcc。被调用的函数并没有得到 continuation。只是它可以异步执行,就成了“超轻量线程”。
LD:假如硬件支持 callcc。好像对保护问题也没啥用。
LD:换个思路。其实 OS 最容易出问题的是硬件驱动,所以尽量让硬件标准化,别每个硬件都搞一套自己的驱动。让一套驱动支持多种硬件,问题就解决了。比如 usb 驱动。完全可以做到一类硬件都用一个设备驱动。
IAN:我还是觉得驱动程序 bug 其实可以不导致当机。用内核线程行不行?共享地址空间,但是异步执行。
LD:Linux 似乎就是这样。tasklet,可以被调度的。
IAN:所以驱动程序要是当掉,可以不死对吗?我回去查一下。
LD:看啥错误了。不小心修改了其它模块的内存就完蛋了。其它错误最多硬件本身不能用了。
IAN:所以就是为什么你说再多一个保护级别。
LD:嗯,别碰了内核关键的代码。但是驱动之间还是可以互相干扰的。
IAN:是个不错的折中方案。所以微内核解决了一个不是那么关键的问题。
LD:是的。这个问题不重要。哦,对了,Windows 是微内核的。好像从 2000 开始。
IAN:只是号称吧。Mac OS X 不是号称 Mach 微内核加 BSD 吗?
LD:对。MacOS 也是微内核。
IAN:那他们怎么解决的性能问题呢?
LD:不知道。Windows 蓝屏可不少,显然没做到完全隔离。至于 Mac,不清楚为啥那么稳定。
IAN:根据我们之前的讨论,所以 Mac 微内核可能是假的。Mac 稳定是因为它的 driver 就没几个吧,硬件都是固定选好的。
LD:嗯,也是稳定的主要原因。
IAN:这个英明了…… 而且看来微内核在集群方面也没什么用处。
LD:集群,每个计算机是一个 node。挂了也不怕。
(8 月 20 日继续讨论)
IAN:我发现这个 paper:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.361.4009&rep=rep1&type=pdf
IAN:Linux 跑在 L4 微内核上,开销只有 5%。
IAN:L4 的做法跟我昨天想的一样,把传递的参数映射到另一个进程的地址空间。就不需要拷贝了。
IAN:代码在这里:http://os.inf.tu-dresden.de/L4/LinuxOnL4
LD:好处真的很大么?
IAN:好处就是微内核的好处,隔离。可能看各人需求了。一个99.99%可靠的系统,和一个99.99999%可靠的系统的差别?
IAN:不过似乎高可靠需求都去用VxWork之类的了。
IAN:5%的开销还可以接受…… 进程切换开销貌似没有提,用的地址映射方法。
LD:cross address space
IAN:刚买了个TP-link路由器,里面跑的vxworks。
LD:tplink不是Linux?
IAN:新的tplink AC1900,改成了VxWorks。Airport extreme也是vxworks。
LD:why?
IAN:实时操作系统,可靠性高吧。
LD:可靠性应该是最高的之一。卫星、武器都用。
IAN:波音 787 也用这个。各种火星车。
IAN:还有个 GreenHills Integrity DO-178B 实时操作系统 https://www.ghs.com/products/safety_critical/integrity-do-178b.html。F35 用的。
IAN:Much of the F-35’s software is written in C and C++ because of programmer availability; Ada83 code also is reused from the F-22.[168] The Integrity DO-178B real-time operating system (RTOS) from Green Hills Software runs on COTS Freescale PowerPC processors.
IAN:Freescale PowerPC…
LD:有个叫“rtems”的os,我一直很关注。
IAN:
Safe and secure by design
- RTOS designed for use in reliable, mission critical,
safety critical and secure (MILS & MLS) applications
- Based on modern microkernel RTOS design
- Fast, deterministic behavior with absolute minimum interrupt latencies
IAN:Based on modern microkernel RTOS design… 看来微内核是可靠一些。
LD:我们的一个mcu就是freescale的powerpc
……
(如果你有什么不同意见,欢迎联系我,或者加入 Freenode 频道 #microkernel)