鸿蒙微内核不是 Linux ,为什么可以跑 Linux 甚至模拟 Linux 容器?

5,718 阅读11分钟

恰好刚刚华为正式发布了了他的 PC 产品,而在之前发的 《鸿蒙 PC 发布之后,想在技术上聊聊它的未来可能》 文章后,在不同平台的评论区都有人提到了这张图,主要是说鸿蒙微内核不是 Linux ,也不是 Linux 套壳,但是能兼容提供 Linux 环境:

去年华为也已经发布过微内核的论文 ,那就可以基于现有资料简单聊聊,为什么鸿蒙的微内核可以做到既不是 Linux 又能跑 Linux

为什么不是 Linux

首先我们聊为什么不是 Linux,鸿蒙内核属于微内核,也就是核心内核的功能被精简到最基本的部分,例如多进程调度和通信,而将大多数系统服务移至用户态实现 :

  • 内核态(Kernel Mode): 核心且高频访问的服务,如进程与线程管理、内存管理(通常是核心子集)、以及基本的进程间通信(IPC)机制等,这些频繁访问的功能在内核态运行
  • 用户态(User Mode): 更高层次的系统服务,例如设备驱动程序以及网络协议栈等,则被移至用户态运行 ,特别是网络通信和设备驱动等高风险功能都隔离在用户态

所以如下图,和 Linux 的宏内核(左)对比,微内核架构大部分实现其实在用户态:

那一般微内核的实现自然就是安全度更高,从而提高了系统的安全性(通过组件隔离,减小内核的攻击面),当然也带来了 IPC 的频率增加引发的性能开销,所以在微内核架构里,高性能的 IPC 机制至关重要,因为用户态服务之间以及服务与内核之间的通信非常频繁。

论文里提到过,手机(约每秒41,000次)和车载(约每秒7,000次)的 IPC 频率

不过鸿蒙表示其微内核的紧凑结构(比如 File System 和 Mem Mgr 合并)极大地提升了 IPC 性能 ,一些频繁访问的核心服务还是会保留在内核态,同时对应的一优化有:

  • 在某些场景用类似 RPC 的同步调用替代 IPC ,核心内核直接进行切换,绕过调度,只切换堆栈/指令指针(避免切换其他寄存器)和保护域
  • 另外就是上图的,「内核态」(IC0) 和「用户态」(IC2) 之间,多定义了一个特殊的隔离类 IC1(也属于内核态),受信任和对性能要求高的服务都运行在 IC1,某种程度是放松受信任服务之间的隔离来减少 IPC 开销

另外,鸿蒙的一个特色就是分布式,内核不仅支持本地IPC,还支持分布式 IPC / RPC ,从而实现了跨设备的远程 IPC 调用,并为分布式 Binder 场景调用提供核心基础。

例如内核实现了一类名为 “archsyscall” 的系统调用,专用于支持微内核特性,包括 IPC 和 RPC ,而对于 RPC 机制中的核心内核资源(例如 ACTV 和 ACTVPOOL )的访问,则通过一种基于能力(capability-based)的机制进行控制 。

而鸿蒙对于内核分布式 IPC 原生的支持,也让分布式操作成为内核层面的「一等公民」,这也是 HarmonyOS 分布式生态系统的基石?

还有还有一个差异就是,Linux 作为通用操作系统,它的 CFS 调度器力求公平,确保多任务环境下各进程都能获得合理的CPU时间,而鸿蒙的确定性时延引擎,则更侧重于用户交互的流畅性和关键任务的实时响应:

侧重于通过实时分析和预测来进行更优的系统资源分配 ,主动优先处理关键任务以保持系统流畅性,任务会按优先级严格划分,与用户操作体验直接相关的关键进程和关联任务,会被在线标记并优先调度。

所以通过设计理念和机制对比,可以看出来鸿蒙微内核确实在技术实现上区别于 Linux :

特性鸿蒙内核Linux 内核
内核类型微内核 (混合形态)宏内核
主要设计目标安全性、模块化、分布式操作、实时性通用性、高性能、开放性
核心架构服务主要在用户态,部分核心管理器在内核态所有核心服务均在内核态
IPC 机制高性能本地及分布式 IPC / RPC多种 IPC 机制 (管道、套接字、System V IPC等)
默认调度方法确定性时延引擎完全公平调度器 (CFS) + 其他 (FIFO, RR, Deadline)

兼容 Linux

那为什么鸿蒙内核不是 linux ,但是却可以兼容 linux ,这就不得不提鸿蒙内核里的基础三大件:POSIX、ABI 和 HDF。

我们简单先通过这个表格,可以看到三大件起到的主要作用:

机制关键词主要功能
POSIX 兼容性内核抽象层 (KAL), musl libc提供标准的类 Unix 应用编程接口
Linux ABI 兼容性ABI 兼容垫片层 (Shim Layer), lsyscall (RPC分发)支持预编译 Linux 二进制程序的执行
硬件驱动框架 (HDF)OSAL, PAL, khdf/linux, 用户态驱动容器实现跨内核、跨平台的驱动开发与复用,支持 Linux 驱动

POSIX

POSIX 标准本身就定义了一系列应用程序的编程接口,目的是增强不同操作系统间的源代码可移植性,而在鸿蒙内核里,主要是由内核抽象层 (KAL) 和 musl libc 来支撑。

内核抽象层(KAL)是鸿蒙实现跨内核兼容性的关键组件,它的核心设计目标是屏蔽底层不同操作系统内核(在 OpenHarmony 可能是 LiteOS、Linux 内核,在鸿蒙NEXT是微内核),从而为上层软件提供一套统一的、稳定的内核能力接口 。

这些接口覆盖了操作系统的核心功能,包括进程与线程管理、内存管理、文件系统操作、网络通信以及外设管理等。

而在微内核下,当上层应用或库发起一个 POSIX 调用时(例如read()write()fork()),KAL 会负责将这个标准化的 POSIX 请求,转换为对鸿蒙微内核相应服务的请求或一系列操作。

另外还有 musl libc ,musl libc 是一个以轻量级、高性能的 C 标准库实现,鸿蒙对它进行了一定的优化和裁剪,移除了一些不适用于此类设备的接口 。

所以在「用户态」应用通过调用 musl libc 提供的 POSIX 函数(如pthread_create()创建一个线程,或open()打开一个文件)时, musl libc 的这些函数实现在需要与内核交互时,内核抽象层就(KAL)介入,然后将这些请求,「翻译」成对鸿蒙微内核内部特定服务或原语的调用:

例如,一个文件打开操作,可能会被 KAL 转换为对微内核中文件系统服务的 IPC 请求,对于线程创建,KAL 可能会调用微内核的进程/线程管理服务来创建相应的执行实体。

因此,POSIX 兼容性并非由单一组件完成,而是由用户态的 musl libc(提供API)和内核态的 KAL(连接API与微内核服务)共同实现

ABI 兼容性

ABI 一般指的是应用程序二进制接口,指的是预编译的二进制程序(如可执行文件、动态库)无需重新编译,就可以在「兼容」的不同系统上正确运行的能力。

为了实现 Linux ABI 兼容性,鸿蒙设计了一个 ABI 兼容的垫片层(Shim Layer),这个垫片层主要扮演翻译官的角色,也就是前面 POSIX 聊到的 「翻译」。

而这个针对 Linux ABI 的垫片层会被部署在内核空间(IC0),它的核心功能是将 Linux 应用发起的系统调用(syscalls),重定向到鸿蒙微内核的 IPC 机制,并作为全局状态信息的一个中央存储库,比如:

当一个 Linux 二进制执行一个系统调用指令(例如通过int 0x80syscall指令)时,这个垫片层会截获该调用,然后解析它的意图(即确定是哪个Linux系统调用以及相关参数),最后将其转换为对鸿蒙微内核相应服务的一个或多个 IPC 请求。

另外,这个垫片层不仅处理系统调用,还可能会处理 Linux ABI 相关的其他方面,如信号传递机制、进程内存布局、ELF 二进制文件的加载和解析方式等。

比如 ABI 兼容垫片层同时支持 AOSP 和 OpenHarmony 的二进制兼容性,所以大概率垫片层可以根据目标ABI(Linux、AOSP)加载不同的兼容模块。

而在调用翻译上,鸿蒙内核通过一种被称为lsyscall的机制来实现对 Linux 系统调用的支持 :

  • Mapping:将标准的 Linux 系统调用映射到鸿蒙内核内部定义的对应功能标识
  • Reconstruction:在鸿蒙的微内核架构下,使用微内核提供的服务和原语来重新实现这些Linux系统调用的功能

所以 lsyscall 会有许多不同的类型。

另外 ABI 兼容也是 iSulad 等容器能运行的关键,也是「卓易通」支持 apk 运行的基础,所以为什么「卓易通」的性能还过得去,主要也是提供的 android 的模拟器环境实现的还过得去。

HDF

最后硬件驱动框架(HDF)是鸿蒙操作系统中负责管理硬件驱动、实现硬件抽象和解耦的关键子系统,主要用于简化驱动开发和移植的复杂度

HDF 架构强调平台解耦和内核解耦,也就是 HDF 驱动理论上可以运行在不同的操作系统内核(如鸿蒙微内核、Linux内核、LiteOS)之上,并且可以适配不同的硬件平台。

所以通过 HDF 本身就可以让鸿蒙支持 Linux 内核驱动,并且在鸿蒙内核还支持用户态驱动容器 (User-mode Driver Container) ,这个机制允许将一些 Linux生态的设备驱动加载到用户态空间中运行,而不是传统的内核态:

HDF 负责驱动的加载、管理以及提供与系统其他部分的通信接口,而「容器」则为这些驱动提供了一个隔离的、模拟了部分 Linux 内核环境的运行空间。

最后

所以,可以看到,通过这三大件,一个 Linux 应用的调用,会经过 POSIX 兼容性(musl libc + KAL),然后通过 ABI 兼容 (Shim Layer),最后通过 IPC 访问到所需的内核支持,而 HDF 提供了驱动兼容,从而实现了 Linux 的兼容运行环境。

所以虽然鸿蒙微内核不是 Linux ,但是它可以提供出 Linux 兼容,甚至翻译出 Linux 模拟环境

其实这也是 iSulad 容器在鸿蒙微内核上运行并创建 Linux 容器环境的核心,也是为什么「卓易通」能实现 Android 模拟器的基础支持。

另外,关于兼容时的代码传染性部分,目前鸿蒙内核也是基于用户态独立进程进行了隔离,比如驱动容器(LDC)复用Linux设备驱动程序:

另外,回到鸿蒙 PC 上,在 PC 上如果具备了完善且高效的 POSIX 兼容性和基础的Linux ABI兼容性,那么理论上就为之前我们聊鸿蒙 PC 的 Wine 的移植和运行提供了可能性。

并且华为还有类似 ExaGea 毕昇编译器支持,说是实现无源码迁移,ExaGear 作为二进制翻译器,能够将 x86 指令动态或静态地翻译成ARM 指令,从而允许 x86 应用在ARM设备上运行,这也算是一个基础支持。

当然,行不行是一回事,好不好用又是另一回事,这里讨论的是可行性。

所以,从这个角度看,微内核确实不是 Linux 套壳,也可以看出来,鸿蒙微内核确实是一个大工程,只是它某些部分不需要从零开始。

参考资料