Microkernel Goes General: Performance and Compatibility in the HongMeng Production Microkernel

杨镇源 于 2024-08-08 发布 浏览量

Microkernel Goes General: Performance and Compatibility in the HongMeng Production Microkernel

原文

1. Introduction

微内核的特征:微内核将内核中的功能最小化,并将文件系统和设备驱动程序等组件移动到隔离良好、特权最低的操作系统服务中,从而实现了比Linux等单片内核更好的可靠性、安全性和可扩展性。

单内核(Linux)存在的不足

微内核(SOTA)存在的不足

微内核改造为通用OS内核面临的主要挑战

Capability-based access controlCapability被简单地称为“密钥”,它是指定资源并授权对其进行某种访问的单一事物。该Capability是不可伪造的权威令牌。 假设有一个文件系统,文件A有如下权限:
- 用户U1可以读和写 - 用户U2可以读 在能力模型中,这些权限将由不同的能力来表示: - 能力C1:允许U1对文件A进行读写操作 - 能力C2:允许U2对文件A进行读取操作 这些能力可以被系统安全地分发和管理。若U1需要将读取权限传递给U3,系统可以创建一个新的能力C3,仅包含读取权限,并将其安全地传递给U3。

HongMeng做出的关键设计决策:

2. The Case for a General Microkernel

2.1 回顾微内核

2.2 通用微内核的需求

2.3 Linux操作系统存在的问题

Linux已经主导了服务器和云市场,并且越来越多地渗透到PC和嵌入式等其他领域。然而,它是以牺牲安全性、可靠性和性能为代价的,特别是在新兴场景中。

“与上游同步”是指保持软件或代码基的更新和维护,与其原始或主版本(即“上游”版本)保持一致。这通常应用于开源软件项目,其中“上游”是指软件的官方源头或主要开发者发布的版本。例如,在Linux内核开发中,当开发者对内核进行特定的定制时,保持与上游版本的同步意味着定期将上游的更新(如bug修复、安全补丁和新功能)合并到他们的定制版本中。

3. Revisiting Microkernel for Going General

3.1 Microkernel at Scale

观察:

3.2 Overview of HongMeng

HM遵循微内核的核心设计原则,但又不至于极端,通过谨慎的妥协来解决新兴场景中的性能和兼容性挑战。

HM的设计决策

设计原则:

  1. 保持最小化
    • 微内核的安全性、可靠性和可扩展性源自三个基本的架构设计原则,包括分离策略与机制、解耦和隔离操作系统服务,以及实施细粒度访问控制
    • HM仅在核心内核中保留最小和必要的功能,包括线程调度器、串行和定时器驱动程序以及访问控制。所有其他功能都在隔离的操作系统服务中实现,例如进程/内存管理器、驱动程序和文件系统。此外,HM采用细粒度的访问控制以保持最小权限原则。服务只能访问对功能至关重要的严格受限资源(内核对象)。因此,HM继承了微内核的安全性、可靠性和可扩展性
    • Retained:具有良好隔离和最低权限的系统服务的最小化微内核
  2. 性能优先
    • 微内核的巨大优势因新兴场景中其架构固有的性能问题而受到损害。因此,HM并不会强制执行统一但过强的隔离,而是提供结构上的支持来组装系统,以满足性能和安全要求
    • Flexibilized:通过提供结构性支持以实现灵活组装,适应多样化场景,从而优先考虑性能。
  3. 最大化生态兼容性
    • HM通过一个shim(上图中的❸)实现与现有软件生态系统的集成,确保Linux ABI兼容性,该shim将所有Linux系统调用重定向到适当的操作系统服务,并作为中心存储库存储和转换Linux抽象(例如fd),以高效支持如poll等功能
    • HM通过驱动程序容器(上图中的❹)复用未修改的Linux设备驱动程序,这种容器直接从主线Linux中派生所需的运行时,所需工程工作量较小
    • Enhanced:通过实现 Linux API/ABI 兼容和高性能驱动程序重用来最大限度地提高兼容性。

HongMeng的威胁模型: HM保留了微内核的架构设计原则,因此维持了类似于现有微内核的威胁模型,这一模型防止恶意应用程序和操作系统服务访问彼此的内存,并确保数据的机密性、完整性和可用性(CIA),但有以下不同之处:

4. Performance Design of HongMeng

4.1 Synchronous RPC-like IPC Fastpath

IPC通常假设两端是对称的,具有相同的执行模型。因此,以往的研究提议异步IPC可以避免在多核上的串行化,允许双方在不阻塞的情况下继续执行。

然而,在新兴场景中,作者观察到大多数IPC都是过程调用(procedure calls),调用方和被调用方可以清楚地识别。此外,操作系统服务主要是被动调用的,而不是连续工作的,并且应用程序的后续操作大多依赖于过程调用的结果。因此,同步远程过程调用(RPC)是服务调用更合适的抽象。

HM采用类似RPC的线程迁移作为服务调用的IPC快速路径。当发送IPC时,核心内核执行直接切换(绕过调度),只切换堆栈/指令指针(避免切换其他寄存器)以及保护域。

性能问题 尽管HM绕过了调度并避免切换寄存器,但由于权限级别/地址空间切换和缓存/TLB污染(占总IPC成本的50%),仍然面临显著的性能下降。

Resource Allocation

Resource Exhaustion

如何解决“堆栈池耗尽而出现内存不足(OOM)时,操作系统服务无法分配新的堆栈来处理IPC请求”的问题:

HM通过保留一个单独的堆栈池来缓解这一问题。一旦发生OOM,内核将使用该池同步IPC到内存管理器进行内存回收(反复进行),直到用户的IPC成功。因此,保证了应用程序的IPC能够被正确处理。

Resource Accounting

4.2 Differentiated Isolation Classes

OS服务的隔离

将所有操作系统服务放在用户空间中可能会提高安全性,但无法满足新兴方案中的性能要求。作者观察到,并非所有服务都需要相同类别的隔离。

隔离等级0(IC0)、核心TCB: 经过仔细验证的、极其性能关键的、可信的操作系统服务,如ABI兼容的shim(部署中唯一的IC0服务)。

IC0威胁模型: IC0是核心TCB(Trusted computing base,可信计算基础)的一部分,任何被破坏的IC0服务都可以任意读取和修改其他服务的内存。因此,放置在IC0的服务应经过仔细验证以避免核心内核损坏。

隔离等级1(IC1)、机制强制隔离: IC1适用于性能关键和经过验证的操作系统服务。HM将这些服务放置在内核空间中,并使用机制在服务之间强制隔离。具体来说,HM仔细将内核地址空间划分为不同的域,并为每个服务分配一个唯一的域(IC0/核心内核也驻留在一个唯一的域中)。HM使用ARM观察点Intel PKS来防止跨域内存访问。 为防止这种情况,HM采用二进制扫描和轻量级控制流完整性(CFI,利用ARM指针认证(PA))来确保服务无法执行包含特权指令的非法控制流,并使用安全监视器来保护页表免受代码注入,同时通过VM退出来捕获任何特权指令,作为CFI的补充。(看不懂)

决策:并非所有的操作系统服务都需要相同类别的隔离。采用差异化的隔离类来放松受信任服务之间的隔离,以提高性能。

4.3 Flexible Composition

虽然直观上操作系统服务应该是良好解耦的,例如文件系统和内存管理器,但是作者观察到操作系统服务并不是对称的,因为某些功能需要特定服务之间的紧密合作。例如,文件系统并不是访问文件的唯一入口。POSIX支持通过内存管理器读取文件的文件映射。 (举个例子,假设你有一个大文件需要频繁读取。如果使用传统的文件I/O方法(如fread或read),每次读取都需要进行系统调用,这样会增加开销。而通过内存映射(通常使用mmap函数),你可以将整个文件或文件的某一部分映射到内存中,这样你就可以直接通过指针操作来读取文件数据,像操作数组一样)

隔离等级在同类操作系统服务之间强制执行相同的隔离。因此,没有进一步的结构性支持,HM仍然面临与宏内核相比的性能下降。

性能: Linux > 合并后 > 合并前

安全性: 在实践中,由于智能手机中文件操作的频率极高,其性能目标只能通过将文件系统与内存管理器合并来实现。然而,与宏内核相比,安全性仍然得到提高(与其他服务隔离)。

部署经验:使用差异化隔离等级,HM支持灵活组合,允许关键组件灵活组装(用户空间或内核空间,分离或合并),能够根据场景需求探索隔离和性能之间的权衡,并能够使用相同的代码库从路由器扩展到智能手机。

决策:操作系统服务是不对称的。协调紧密耦合的操作系统服务,并灵活地组装系统,以满足各种场景下(服务合并,尤其是内存管理器和文件系统,手机)的不同需求。

4.4 Address Token-based Access Control

尽管能力(capabilities)在描述内核对象的外部关系(即授权链)方面非常有效,但访问它们的内部内容需要将令牌与操作一起发送到核心内核,这会由于特权切换和多个元数据表的访问而引入显著的性能开销。

HM提出了一种基于广义地址令牌的方法,可以应用于更广泛的对象,从而实现高效的共同管理。

具体来说,如上图所示,在HM中每个内核对象被放置在一个独特的物理页面上。将内核对象授予操作系统服务需要将该页面映射到其地址空间(❶)。因此,映射的地址作为令牌,用于直接从硬件访问内核对象,而无需内核参与。内核对象可以被授予(映射)为只读(RO)或读写(RW)。操作系统服务可以在不涉及内核的情况下读取只读的内核对象。要更新它们,需要使用新的系统调用writev,传递目标地址和更新值,核心内核将通过参考内核对象的元数据来验证权限(❷)。对于读写内核对象权限,一旦授予,操作系统服务可以在不涉及内核的情况下更新它们(❸)。此外,对于小于一个页面且具有相同属性(权限)和相似生命周期的对象,HM在分配时将这些对象批量放入一个页面,从而允许它们被集体授予和撤销。

功能、安全性、同步、性能、使用场景…

决策:能力机制将内核对象隐藏在内核中,并在数据平面上进行干预(效果并不理想)。补充使用地址令牌以实现高效的共同管理。

4.5 Policy-free Kernel Paging

为了提高处理匿名内存页面错误的性能,HM预先做出策略驱动的决策,并在核心内核中留下无策略的页面错误处理机制,从而消除了关键路径上的额外IPC往返。具体来说,内存管理器提供匿名内存的地址范围以及一些预先分配的物理页面。如图7所示,如果页面错误在范围内触发(❶),核心内核可以直接将其映射到预先分配的物理页面(❷和❸),并记录一个操作日志(OPLog,❹),内存管理器将使用该日志异步更新其内部状态(例如,映射的匿名页面计数器)。否则,如果地址在指定范围之外(非性能关键)或预先分配的页面已耗尽,核心内核将向内存管理器发出IPC。

涉及的内核对象通过地址令牌由内存管理器共管理,包括页表、操作日志、记录匿名内存布局的VSpace存储预分配页面的PCache

妥协 通过提前做出政策驱动的决策,策略(是否/哪些进行映射)仍然保持在核心内核之外。唯一妥协的能力是在预分配到PCache后更改政策,这降低了灵活性。PCache还引入了一些额外的内存占用。然而,由于PCache可以定期补充(不在关键路径上),其大小保持相对较小,使这些权衡是可以接受的。

决策:通过抢占政策驱动的决策来启用无政策内核分页

5. Compatibility Design of HongMeng

5.1 Linux ABI Compatibility

在新兴场景中部署需要与 Linux ABI 兼容,这在多服务器微内核中带来了挑战。

HM通过将符合ABI的shim放置在IC0(内核空间)中实现Linux ABI兼容性,该shim将Linux系统调用重定向为针对适当操作系统服务的IPC(通过系统调用编号识别,本地系统调用绕过shim)。

部署经验: HM通过了所有AOSP兼容性和供应商测试套件(CTS/VTS)的测试,这些测试检查了内核功能和驱动程序行为。尽管大多数二进制文件可以直接运行,但作者发现一些应用程序依赖于不稳定或未记录的Linux行为,在HM上运行失败。

决策:通过与ABI兼容的shim实现LinuxABI 兼容性。

5.2 Driver Container

Linux无疑拥有最丰富的设备驱动程序生态系统。此外,一些驱动程序并不提供源代码,这使得移植变得具有挑战性。因此,重用Linux驱动程序对于广泛部署至关重要。

HM通过驱动程序容器重用Linux驱动程序,旨在找到兼容性、工程努力和关键路径性能之间的最佳平衡点。

兼容性 Linux驱动容器(LDC)通过重用Linux代码库作为用户空间运行时,提供所有必要的Linux KAPI,使现有的 Linux 驱动程序能够无修改地运行。HM创建了另一个设备管理器,管理 Linux和本地驱动程序容器(本地驱动程序所在的地方)。除了初始化驱动程序容器外,它还在虚拟文件系统 (VFS) 中注册条目 (❶ 在上图中),以便通过VFS的驱动程序调用(例如,ioctl ❷)可以正确重定向到相应的驱动程序容器 (❸)。

工程量

关键路径性能 HM通过在本地驱动程序容器中创建一个双驱动程序来应用控制平面和数据平面分离,该双驱动程序处理性能关键路径上的I/O IRQ(上图中的❹)。双驱动程序重写数据处理程序,因此可以在较弱的隔离下强制执行(位于内核空间的IC1),从而显著提高性能。控制平面包含像初始化/挂起/恢复这样的繁琐程序,仍然保留在LDC中(❺)。

决策:通过控制/数据平面分离的驱动程序容器高效重用Linux设备驱动程序。

6. HongMeng in the Wild

HM的核心内核主要是用一个有限的C子集实现的,包含90,000行代码(LoC),其中包括基本功能。所有其他操作系统服务都是解耦的,可以单独部署,总计超过100万行代码。HM的构建系统可以根据为各种场景指定的详细配置组装操作系统服务,例如将操作系统服务放置在不同的隔离类中或合并某些操作系统服务。

对于更广泛场景的容错(例如,丰富操作系统中的有状态操作系统服务)需要额外的努力来存储状态并保持其一致性,这一点留待未来工作。

在对性能要求高的场景中,如智能手机,HM将性能关键的操作系统服务放置在IC1(内核空间),包括进程管理器、内存管理器、文件系统和本地驱动程序容器,并将文件系统与内存管理器合并。Linux驱动程序容器和其他非性能关键的操作系统服务,如CPU频率调节器和电源管理器,仍然保留在IC2(用户空间)。

Performance

Lessons and Experiences