华为鸿蒙系统HarmonyOS学习之十:鸿蒙HarmonyOS微内核技术
一、前言
把操作系统中更多的成分和功能放到更高的层次(即用户模式)中去运行,而留下一个尽量小的内核,用它来完成操作系统最基本的核心功能,称这种技术为微内核技术。
在微内核中通常提供了以下的功能:
- 进程/线程管理
- 低级存储器管理
- 中断和陷入处理
微内核具有以下的特点:
- 足够小的内核
- 基于客户/服务器模式
- 应用机制与策略分离原理
- 采用面向对象技术
机制与策略的概念
- 机制:实现某一功能的具体执行机构(what)
- 策略:在机制的基础上借助于某些参数和算法实现该功能的优化(how)
微内核的优缺点
优点:
-
系统服务模块化,可移植性高;
-
内核安全性提高(模块内部的 Bug 不影响内核稳定,将黑客利用软件漏洞造成的破坏限制在单个模块内部);
-
可以多套系统服务共存,相当于同时运行多种操作系统;
-
稳定统一的接口(可以独立维护私有驱动以及服务,不需要跟内核源码绑定);
-
在商业上,微内核可以避免代码受到一些开源协议的影响,比如 GPL 协议;
-
内核精简,可以进行形式化验证,利用数学证明内核的安全性;
-
数学可证明的实时性;
-
非常适合多处理器系统设计,在多处理器核心计算机上,互相依赖的系统服务可以同时运行;
缺点
-
通过进程通信的方式交换数据或者调用系统服务,而不是使用系统调用,造成额外的操作系统开销;
-
使用一些频繁使用的系统服务时,比如网络收发数据,造成的进程上下文切换对操作系统来说也是一个负担;
-
由于系统服务高度模块化,系统服务之间存在大量的内存复制;
-
对互相之间存在复杂调用关系的系统服务,难以设计通信接口;
-
系统服务与内核在地址空间上分离,造成代码局部性差,降低了 cache 命中率。
二、微内核的发展历史
微内核这个概念从提出开始到现在就在一直处于不断地发展、完善进步之中,到目前为止可以分为三个历史时期,也可以称为三代。
第一代微内核:从无到有
第一代微内核的主要代表是 Mach,由美国卡耐基梅隆大学的 Avie Tevanian 和 Richard Rashid 主导开发的。当时正是UNIX 发展正如日中天时期,因此Mach不可避免的受到UNIX的影响,最起码兼容unix是最起码的考量,但是与 UNIX 不同的是 Mach 使用微内核架构。Mach 以 IPC 是作为所有系统服务与内核交换数据的基础机制,充分运用 IPC、虚拟内存、多进程等特性将冗余的系统服务移出内核作为进程运行。
1986年,Mach 发布了第2版,但此时 Mach 内核并不提供完全的系统服务,该本的内核包含了大量 4.3 版本的 BSD 系统(UNIX的一个分支)代码提供系统服务,并且 BSD 系统服务运行在内核状态,这导致 Mach 内核的代码体积甚至大于常规 UNIX 内核。这两个版本达成了如下的目标:
- 验证了微内核的可行性;
- 在多处理器计算机上进行移植验证了微内核在多处理器计算机上的运行;
- 最后为了提高 IPC 的效率,Mach 使用共享内存机制来完成 IPC。
Mach 的共享内存机制是在虚拟内存技术的支持下实现的,只有需要对内存进行写入时才进行复制。这么一处理比每次都复制一遍内存节省了内存使用同时又加快了 IPC 机制的处理时间,这个改进称为写时复制,并且在如今的通用操作系统如 Linux 中常常用到。经过测试,Mach 2.5的效率最多比 UNIX 少 25%,但是考虑到 Mach 带来的可靠性、可拓展性、安全性,这个效率损失尚可以接受。此时 Mach 内核还不算完全的微内核。而考虑到微内核可以更高效地利用多处理器计算机的处理器核心资源,寄希望Mach 把系统服务都搬到内核之外后可以把运行效率损失降下来。开放软件基金会(Open Software Foundation,OSF)宣布下一代系统 OSF/1 将基于 Mach 的内核, 众多公司开始采用这个内核:如NeXTSTEP 使用 Mach2.5(未与苹果合并之前);IBM 利用 Mach 构建 Workplace OS;苹果公司基于 Mach2.5 打造其操作系统内核 XNU。
Mach 3.0 于 1990 年发布,由于在系统服务之间完全使用 IPC 通信,而不是向宏内核那样直接进行函数调用,即便是多处理器机器上运行也性能损失惨重,Mach 3.0 最多比 UNIX 损失 67% 运行效率,这导致 Mach 3.0 以及其所代表的第一代微内核设计被看衰。此后断断续续有在 Mach 的基础上对性能进行提升的尝试,但是均不太理想,至此 Mach 成为了微内核第一代先驱者。
第二代微内核:解决性能问题
第二代微内核的主要代表是 L3 和 L4,以及 QNX 系统使用的 Neutrino 内核。前面第一代的微内核 Mach 由于效率问题原因失败了,但是微内核的理念并没有被放弃,Jochen Liedtke 认为 Mach 的 IPC 效率低下的原因就是因为 IPC 部分不够精简,于是有了L3 和 L4 微内核,对 IPC 部分进行了很彻底的精简优化:
- 内核的 IPC 机制只是单纯地传递信息,诸如安全权限检查这类的代码都省略掉,省略掉的功能全部由用户进程自己处理。如此一来 IP C功能部分的代码执行时间大大缩短;
- IPC 不使用内存传递消息,而使用寄存器传递消息,同时限制 IPC 每次传递的信息长度,这样省去了对内存的访问时间。L4 微内核的 IPC 速度经过测试要比 Mach 快 20 倍,这个令人惊讶的优化效果吸引了众多的目光,使微内核的研究重新火热起来。后面 L4 内核又发展出了很多相关系统,比如 Pistachio、L4/MIPS 与 Fiasco 等等,这些内核组成了 L4 的大家族。
第二代微内核的代表除了有 L4 内核,也还有其他微内核比如 Exokernel、Rambler 等,但做的比较成功的是:黑莓公司旗下的 QNX 系统所使用的 Neutrino 内核(QNX,1980年诞生,最初以 QUICK UNIX 为名,后改为 QNX;2004 年 QNX 被 Harman 国际收购;2010 年 Harman 国际下被黑莓收购,QNX 成为黑莓旗下的资产),QNX 主要为高可靠领域提供解决方案,比如交通、能源、医疗、航天航空等。
第三代微内核:主要重视安全问题等
在前面两代的微内核的基础上,第三代微内核蓬勃发展,许许多多微内核都被开发出来,主要代表有:seL4、Fiasco.OC、NOVA 等。
本来第一代微内核的设计隔离了使内核安全性降低的系统服务,让系统服务漏洞不会影响内核,进而提高了内核安全性,可以说是关上了破坏系统的门, 但是第二代系统却又给攻击者开了个窗户。
由于第二代微内核在内核中省去了关于安全性检查等步骤,把所有关于安全检查功能的实现都交给系统服务自己去实现,这导致系统服务的通信接口直接暴露给用户态,任何进程都可能无限制地请求系统服务,系统服务不得不花费额外的代价来区分请求是否合法,容易造成拒绝服务攻击。
比如正常的文件服务应该是从虚拟文件系统服务->文件系统服务->磁盘驱动服务这个流程来完成的,但是如果攻击者如果绕过虚拟文件系统服务,直接无限制地请求攻击者本身没有权限访问的文件系统服务,使文件系统服务长期处于满载状态,让其他进程无法通过正常的虚拟文件系统得到文件系统服务。为了增强安全性,且不过分影响性能,人们开始研发第三代微内核。
seL4 是在第二代内核 L4 的基础上发展而来的。seL4 不仅仅继承了 L4 内核家族的高性能特性,还具备基于端点(enndpoint)的 IPC 机制。
这种 IPC 机制最大的特点是使用了能力空间的概念,进程在使用 IPC 请求系统服务时必须具备相对应的能力,进程持有不可伪造的令牌来表示拥有请求某种服务的能力。令牌可以被复制,可以被转移,还可以通过 IPC 进行传输。令牌其实是一个指向存在于内核空间内核对象的指针,所以普通进程并不能修改自身以及其他进程的权限分配,但是内核可以对令牌指定的权限进行控制,从而保证了用户态不能绕过能力空间这个机制对系统服务造成滥用。
seL4 还是第一个完全通过形式化验证的内核,通俗说形式化验证就是在数学软件的帮助下使用数学语言自动化地推导检查系统的每一个运行状态。seL4 形式化验证相关论文。
三、微内核与宏内核的对比
宏内核的架构图
微内核架构图
形象一点说宏内核就是操作系统是个大管家,几乎包办一切,用户应用程序的需求直接向内核提出就行;微内核更像一个代理人,几乎所有的驱动、文件系统全部运行在与用户应用程序平级的用户模式下。
如果把操作系统看成一家公司,而宏内核的特点是用户请求直达内核,内核统一安排执行,这代表此公司使用扁平化的管理架构,而微内核的操作系统中则需要设立很多如驱动,文件系统等部门,这显示公司使用制度化、等级化的管理架构。也就是说,如果宏内核代表的是层次简单的扁平化管理风格,微内核则代表多部门的制度化管理风格。
运行效率宏内核更优:形象一点,就类似去政府部门跑公章的经历,很多时间、精力都浪费在了部门(进程)之间的上下文切换(上文已经释义)中了,微内核在效率方面肯定是处于劣势的,所以目前的主流操作系统如Linux和Windows本质上使用的都是宏内核,当然有人会说Windows使用的是混合内核,不过这种混合内核也是以效率优先的扁平化架构,本质上还是宏内核。
宏内核vs微内核,谁更安全?:宏内核采用扁平化管理,扁平化虽然能有比较高的效率,但是难免会在身份鉴别、数据传递的过程中出现纰漏,从而给入侵者可乘之机。微内核将其内核抽象成一个有限状态机,进而证明在状态迁移与跃迁的过程中都不会发生会被恶意利用的漏洞,从而保证整个体系的安全。当然这个安全也有前提:
- 不能有内鬼:即生成内核的编译器、链接器与操作运行的硬件环境如DMA等设备不能被提前恶意植入后门。
- 不能有密码泄露:形式化验证只能保证制度体系本身不出问题,如果用户将自身密码泄露那系统是无法防范的。
我们知道宏内核的操作系统尤其是Windows,经常会暴出安全漏洞,用户在没有泄露密码且没使用问题硬件的情况下,还是会遭到被黑客入侵。所以在安全性对比上微内核可谓优势明显。
宏内核vs微内核,谁实时性强?:效率更优的宏内核在实时性方面的表现其实不如微内核。那些对于实时性要求极高的军用操作系统(如vxWorks等)使用的都是微内核架构。
宏内核vs微内核 谁更适合多核处理器?:宏内核会在CPU核心间不断进行上下文切换,而微内核则不断在进程间进行上下文切换。微内核的回归验证了微内核与多处理器的硬件平台配合会更好
四、鸿蒙的微内核的微内核技术
-
微内核架构包含两类组件:核心系统和插件系统。核心系统的功能稳定,很少变更,其只拥有能使应用运行的最小功能逻辑,这些通用逻辑(例如插件模块的注册、加载、卸载,以及插件模块之间的相互通信等)不涉及任何特定业务;插件系统则具备良好的扩展性,其负责实现特定的业务逻辑,可根据特定业务需求而变更。
显而易见,微内核架构本质上其实是将一个软件系统中的变化部分封装在插件中,从而实现不同业务之间的隔离性,达到系统快速灵活扩展的目的,同时所有特定业务相关逻辑的变更不会影响整体系统的稳定性。 -
设计要点
微内核架构设计有以下三个关键点:插件管理、插件链接和插件通信。
- 插件管理
核心系统需要知道当前系统中共有多少个插件,哪些插件处于可用状态,什么时候加载一个插件,如何加载一个插件等。
实现上述功能的一个常用机制是插件注册表:核心系统提供一个服务来响应插件的注册请求,最终将当前系统的所有插件信息(插件标识,类别,启动方式等)保存起来。存储方式可以选择配置文件存储或者数据表存储等。 - 插件链接
插件链接制定了一个插件与核心系统的通信方式,也就是链接规范,故任何一个可用插件都务必遵从核心系统中该类别插件所制定的链接规范。
常见的链接规范有OSGI(Eclipse),消息队列,依赖注入(Spring),RPC等。 - 插件通信
插件模块的设计是为了达到低耦合目的,也符合这一原则。但一个业务请求往往需要几个插件模块共同协作来实现,这就需要插件之间可以实现相互通信。插件之间的通信则需要通过中央处理器(核心系统)来作为桥梁,故核心系统除去提供上文提及的注册表机制之外,还需要提供类似操作系统总线之类的通信机制。
五、业界其他的微内核系统:Fuchsia、Minix
Fuchsia 是 Google 开发的一款全新操作系统,试图覆盖手机、平板甚至笔记本等一系列领域。Google 为该系统配备了 Vulkan 图形接口、3D 桌面渲染 Scenic、Flutter 应用开发框架,还有一个称为 zircon 的微内核。
zircon 内核是从高通平台的一个 Bootloader 项目:Little Kernel发展而来。zircon内核属于微内核设计,只提供 IPC、进程管理、地址空间管理功能。zircon 区别于以进程或者以文件为核心的设计,zircon 是以内存为核心来设计的,内存在 zircon 中是以对象的方式存在,可以通过 channel 通信机制传递虚拟内存对象(Virtual memory object)的句柄,进程拿到句柄后可以把这块内存映射到自己的空间。
Minix 系统则由荷兰阿姆斯特丹的 Vrije 大学的 Andrew S.Tanenbaum 教授所开发。该系统最大的特点是可以故障隔离,自动重启失败的服务。Minix 使用分层设计,最底层的微内核提供中断处理、进程管理、进程通信等服务,这一层运行在内核态;中间层提供轮回服务(Reincarnation Server)、文件服务、进程管理、X 图形服务以及驱动等,这一层运行在用户态,最上层为用户进程。其中轮回服务负责在中间层的服务出现崩溃时重启这些服务,从而保证服务的自我修复。Minix 由于其自我修复特性被英特尔管理引擎(ME)所选用,该管理引擎主要负责管理英特尔芯片的内部模块。