来自Wiki的图片:
传统上,操作系统的“内核”是系统上运行的所有其他软件都需要的部分。因此,内核对应于可信计算基础(Trusted Computing Base ,TCB)的OS部分,这些部分的正确行为是任何其他部分正确操作的先决条件。
微内核的基本思想是最小化内核,并在TCB之外实现尽可能多的内核。内核应该只导出简单的、低级的操作,希望这些操作能够实现更高效的应用程序。这个想法可以追溯到[Per Brinch Hansen在1970年发表的<The nucleus of a multiprogramming system>],一个好的概述可以在[J. Liedtke. Toward Real Microkernels. 1996]中找到。传统的内核是“单结构的”,在某种意义上说,它们在TCB内以相对非结构化的方式实现其所有功能。从软件工程的角度来看,微内核的优点是显而易见的:
微内核最初受到了极大的热情,在80年代后期,在学术和商业环境中都有很多关于微内核的工作。当人们开始遇到似乎与微内核实现的灵活性和效率有关的内在困难时,最初的热情消退了:
通过对原始微内核理想的各种妥协克服了这些困难。几个效率关键的特性被重新引入内核,并且通过可下载的二进制代码或可信的“内核加载模块”支持向内核添加新特性。
但是,将大多数驱动程序和服务器集成回TCB,在很大程度上消除了微内核方法的好处,最终导致更复杂的单内核操作系统内核。
最近,在微内核理念之后出现了几种第二代实现,它们声称可以解决第一代的灵活性和效率问题。这些实现如何实现这个目标有很大的不同,以下三个具有代表性:
目前尚不清楚这些新一代解决方案是否真正适用于实际操作系统。缺少的是使用上述系统的策略构建的真实操作系统的存在,就像Chorus和Mach是使用第一代微内核策略构建的真实操作系统一样。尽管如此,上述系统的出现给微内核方法的未来带来了巨大的希望。
在八十年代末和九十年代初期,有几个真正的基于微内核的操作系统。也许其中最引人注目的两个是Mach和Chorus。Mach在CMU开发,是最成功的,并且已经被应用到几个商业系统中,比如NeXTSTEP OS。
OS | microseconds | instructions |
Mach | 115.0 us | 1150 |
L4 | 5.0 us | 50 |
Exokernel | 1.4 us | 30 |
SPIN | 102.0 us | 1100 |
3.1 L4
L4是J. Liedtke和他的团队在1995年开发的,是L3的直接后代,L3是第一代微核。L4的从头开始开发,加上它的小尺寸和简单的接口,使它能够摆脱第三种"遗留"代码类型的微内核问题。
L4基于微内核是处理器相关的理论,即像代码优化器一样,微内核本身就不能移植,尽管它们提高了整个系统的可移植性。L4提供了三个抽象,地址空间、线程和IPC,并且只实现了七个系统调用。L4中的线程是用户级的,但是内核支持通信和地址空间管理。最后两个抽象,地址空间和IPC,在L4中特别有趣,下面将详细讨论。
3.1.1 地址空间
L4微内核提供了实现物理内存管理和各种保护方案的基本机制。基本思想是支持内核之外的地址空间的递归构建,如下面的图1所示。
图1 L4中递归构造的地址空间
初始地址空间表示物理内存,并由初始内存服务器拥有。虚拟页面的所有者可以使用L4提供的操作,将其所有权转移到(grant)或与(map)共享,这是一个同意的接收进程。所有者还可以从接收者的地址空间中删除任何共享页面(demap),而不需要在两个进程之间达成任何协议。
此功能允许实现内核之外的内存管理和分页。映射和解调足以在微内核之上实现内存管理和分页。授予仅在特殊情况下使用,以避免双重簿记(bookkeeping)和地址空间溢出。为了验证进程一致性,采用IPC实现内存管理和分页,进一步强调了快速IPC的必要性。
3.1.2 IPC实现
L4继承了L3改进版本的IPC实现,速度惊人,其性能如表1所示。IPC时间的这种数量级改进是通过各种优化技术实现的。下面我们将讨论其中的一些技术,这些技术带来了最大的性能收益。
3.2 Exokernel
Exokernel,于1994 - 1995年在麻省理工学院开发。其开发背后的主要动机是内核提供的抽象代价太高而且限制了灵活性。本论文得到了“end-to-end”论证的支持:应用程序比OSs更清楚它们的资源管理决策的目标是什么,因此,应该尽可能多地控制这些决策。
因此,微内核应该只提供最小必要的原语集,以安全地多路复用硬件资源。高级功能由库OSs提供,库OSs是用户提供的,不受Exokernel信任。为了使Exokernel尽可能简单和高效,甚至它的导出接口也依赖于硬件。大多数时候,Exokernel只是导出硬件功能。
图2 基于Exokernel的应用程序/操作系统的结构
图2显示了基于exokernel的系统的结构,两个应用程序使用不同的库OSs。由于Exokernel必须适应不受信任的高级别OSs,其主要目标是安全地导出和复用硬件原语和资源。Exokernel使用了三种技术来实现这一点:安全绑定、可见资源撤销和中止协议,下面将讨论其中的每一种。
3.2.1 安全绑定
由于资源的实际管理留给了库操作系统,因此必须有一个将资源保护与资源管理分开的机制。安全绑定就是这种机制,Exokernel使用三种不同的技术实现它们:硬件机制、软件缓存和可下载的应用程序代码。
一种常见的硬件机制是TLB。安全绑定可以实现为从虚拟地址到物理地址的映射,例如,作为TLB入口。如果硬件TLB不够大,则将其封装在较大的软件TLB中,以缓存此类映射。在一些Silicon Graphics系统上可用的另一种硬件机制是具有与每个像素相关联的所有权字段的帧缓冲器。在那里,硬件处理帧缓冲区的保护,只有当像素改变所有权时才涉及到Exokernel。还可以将代码下载到内核中,在每个资源访问或事件中调用它来确定所有权以及内核应该执行的操作。包过滤器就是这种代码的一个例子。
实际上,下载代码的这个特性不仅可以用于安全绑定的实现。更一般地说,可以将特定于应用程序的安全处理程序(ASH)下载到内核中,并允许它执行一般的计算。这种功能是基于性能的,用于减少内核和用户模式之间的上下文切换,特别是在时间限制使这些切换不切实际的情况下,如包接收上的网络ack。ASHs和所有下载的代码都是不受信任的,并且通过代码检查(使用类型安全语言)、保护解释和沙箱(与SPIN类似)的组合而变得安全。
3.2.2 可见资源撤销
可见撤销比传统的隐形撤销具有更高的延迟,但允许库操作系统指导解除分配并了解资源稀缺性。Exokernel导出物理名称以提高效率和更好的资源管理,因为这允许消除间接级别,而且物理名称通常编码有用的资源属性。这使得可见撤销成为必要,因为库OS需要更新它的物理引用。
3.2.3 中止协议
由于库操作系统不受信任,因此Exokernel应该适应他们的不合作。当撤销请求没有及时得到满足时,Exokernel有权“强制”打破任何相关的安全绑定,并重新获得所请求的资源。Exokernel通知不友好的库操作系统撤销,但不采取任何更激烈的措施。另一种方法是杀死相关的应用程序,但这是为了减少损失而决定的。
3.2.4 保留
Exokernel方法是非常激进的,它激发了人们对原始微内核的热情。然而,这些微内核的命运应该有一个发人深省的影响。应该注意的是,主要的Exokernel论文没有讨论OSs的几个关键方面,比如文件系统,而且它们对高效框架缓冲区的特殊硬件的依赖感觉像是作弊。因此,硬件级非抽象的Exokernel方法可能只适用于专门的机器代码级应用程序。即便如此,这种不完整性可能只是当前Exokernel实现的不成熟的标志,而不是该方法的固有问题。确实有一篇新的论文,它讨论了高效的“Exo-file-system”的实现。
3.3 SPIN
SPIN,基于Mach微内核的最新版本,增加了下载安全代码的能力,从而扩展了内核。因此,它在某种程度上表明了为抵御第一代微内核操作系统的低迷性能而开发的最新一代技术。因此,这里的介绍既合适又必要。
SPIN使用语言和链接时机制来允许动态扩展内核服务。应用程序可以将新OS服务的代码下载到内核中,因此可以根据自己的特定需求创建细粒度的OS接口。扩展由内核编译器转换,动态链接到内核并在内核的虚拟地址空间内执行。
3.3.1 灵活性
上面的内核可扩展性方法立即提出了安全问题:用户提供的代码可以信任吗?SPIN通过使用类型安全语言Modula-3和沙箱下载的代码来解决这个问题。因此,编译器执行静态分析并插入运行时检查,确保编译后的代码不会违反内核、其他模块或用户级代码的完整性。由于内核不对导入代码的安全性做出任何假设,因此可以声称编译后的扩展不会增加TCB。每个单独模块的隔离保证了如果应用程序崩溃,例如,由于下载到内核的扩展模块错误,系统的其余部分不会受到影响。
SPIN提供了一组用于管理内存和处理器资源的核心服务。它们的级别类似于宏内核操作系统中的内部接口。内核扩展可以将核心服务用作构建块,也可以执行任意计算。核心服务包括支持对虚拟内存的应用程序控制的操作,例如地址的转换服务。核心服务还包括用于进程管理的低级接口,定义要由用户线程包和调度程序处理的一组事件,以及包括确定事件的接收者线程包的全局调度程序。
3.3.2 性能
内核扩展在灵活性和可扩展性方面的优势是显而易见的,甚至可以在线修改内核。至于性能,向内核添加功能在一定程度上减少了内核和进程之间的IPC数量。这在某种程度上补偿了测量的高IPC成本。即便如此,应用于L4的优化也可能适用于SPIN,从而降低了剩余IPC操作的成本。
另一个可能更重要的性能问题是内核编译器的效率。证明代码模块安全并不是一项简单的任务,安装新内核扩展所产生的延迟有时是不可接受的。但是,当前版本的SPIN使用了一个外部编译器,这是对以前的解释器或基于内部编译器的系统的改进。在SPIN中,编译器可以是多任务的,并且内核的大小更小。对编译器接口的进一步改进可能包括缓存已编译的代码以减少分摊的编译时延迟,以及处理嵌套IPC重定向等事务的专门优化。
4) 总结
首先让我们看一下上面检查的三个系统如何满足2.1节中所述的微内核的原始目标。与传统的宏内核相比,这三个系统的性能都是一样的,或者更好,这三个系统都可以支持新的应用程序结构(分别是递归地址空间、库OSs和内核扩展)。那么剩下的就是检查2.1节的枚举列表:
从上面可以看出,当前的微内核已经解决了2.2节中提到的IPC和遗留问题,但是它们似乎并没有解决微内核中高MCPI的问题。这实际上是一个值得关注的大问题,因为随着内部CPU速度的快速增长,缓存性能越来越成为一个问题。然而有人指出,使内核小到足以完全适应缓存,将消除这个问题。SPIN在内核中进行计算的方法也可能解决这个问题,尽管内核很大。
目前这一代微内核的一个共同方面是可扩展性,通过下载代码验证安全。这种能力对于未来的高速网络和分布式OSs显得至关重要,特别是在进程切换的相对成本急剧上升的情况下。因此,奇怪的是L4还不支持内核可下载扩展。然而,阅读L4的论文就会发现,该系统实际上没有很好的网络性能,人们可以猜测,他们用可下载的扩展来纠正这一点只是时间问题。
第二代微内核导出的接口的复杂性差异很大。L4和Exokernel都提供简单的低级操作。L4提供了地址空间和线程管理所需的基本内核抽象,而Exokernel提供了安全的多任务资源所需的裸硬件相关原语。另一方面,SPIN导出各种接口,应用程序看到继承自Mach的第一代微内核接口,以及内核下载代码的内部接口。Exokernel中ASHes的存在更难以区分全局描述。因此,适当的内核提供的操作集可能是有效的低级操作和在需要时使用高级操作扩展内核的能力的混合,例如,支持关键时间的功能,如网络。
Exokernel的硬件依赖可能是一个严重的缺点。我们发现,构建非常低层次的抽象(如L4导出的抽象)是非常依赖于CPU的,对于Intel x86家族的后续成员,需要完全不同的方法。这似乎表明,在Exokernels之上构建低级库OSs可能是每一代处理器都需要重新做的事情。如此高的不可移植性将成为任何真正接受基于Exokernel的操作系统的严重障碍。
总之,我们应该强调我们在引言中已经指出的内容。第二代微内核最重要的责任是完全缺乏基于它们的真实操作系统。只有每天的实践经验才能证明操作系统是真正可行的。由于这些微内核是最新的,它们的最终判断还为时尚早。时间是他们唯一确定的判断。