从底座重建OS内核理论和架构:分布式内核

1,759 阅读12分钟

为什么要设计分布式内核OS?

内核是操作系统最核心的部分。我们通常把内核分为宏内核、微内核、混合内核和外核这4类,我们先来看看这4种内核各有什么优缺点。

宏内核OS

Linux是当前最主流的宏内核操作系统,那么,我就举Linux实现网络数据包发送的例子,看看宏内核操作系统是如何发送数据包的:

图中绿色部分就是内核,从Linux处理数据包发送的架构来看,我们发现整个发送流程还是较长,经过socket、tcp、虚拟内存、网卡驱动等,其中socket到tcp之间还存在用户空间和内核空间的数据拷贝。

微内核OS

那我们再看看,同样是网络数据包发送,微内核操作系统是如何做的?

MINIX-3X-User-System-Communication-From-1.png

图中,我们发现微内核操作系统由于使用的IPC机制进行内核进程和用户进程的通信,因此,一个数据包的发送要经过User process、FileSystem、Device drvier和SystemTask这4个进程,进程之间共6次通信,其中,3和4步还存在用户态和内核态的切换及system_call陷入中断,同时,进程间由于走IPC,也会存在进程上下文的切换,因此,微内核操作系统的性能甚至比宏内核操作系统更差,那么,为什么还需要微内核操作系统呢?

因为扩展性!

我都知道目前Linux主要的IO模型有BIO、NIO、AIO,假设我现在要扩展新IO模型,我们怎么做?

由于IO模型是在内核中实现的,因此,我们只能让内核研发人员在内核中扩展新的IO模型,但是,内核研发人员远远少于用户程序的开发人员,他们什么时候可以完成这个新IO模型的开发,我们是无法预期的。

此时,微内核操作系统有什么优势呢?我们来看看这张图:

The-design-of-Minix-3-Communication-among-components-is-based-on-the-message-passing.png

此时,微内核操作系统的优势就体现出来了,图中,微内核操作系统在内核空间只保留了中断、MMU、调度、IPC,将FileServer、HardDisk Driver等划分到用户空间,也就意味着FileServer、HardDisk Driver这些可以由用户自己开发,那么,基于他们的新IO模型也可以由用户自行开发,因此,大量的用户程序开发者可以很快地开发出新的IO模型,保证了研发的效率。

微内核采用这样的可插拔设计,除了提升了扩展性,也实现了用户自定义组件的互相隔离,避免了互相影响,系统可用性更高。

混合内核OS

由于微内核操作系统存在性能问题,但扩展性好,宏内核操作系统扩展性差,但是性能好,于是,结合微内核的扩展性和宏内核性能的内核设计出现了,这就是混合内核操作系统。

我们来看下混合内核的操作系统的架构长什么样?

这是MacOS的架构,苹果系统也是一个混合内核操作系统,我们发现它把File system放到了内核中,而不像微内核操作系统,File server是用户自定义的,因此,这样的做法保证了文件读写的效率,同时,该系统中的BSD组件又被放在了用户空间,所以,也保证了BSD相关程序可以移植到MacOS,扩展了MacOS的能力。

外核OS

那么,是不是混合内核操作系统已经完美了?

大家有没有发现,混合内核操作系统,由于内核部分基本由相关厂商自己研发,那么,每家要把哪些模块放到内核,可能想法不一,放到内核后,怎么和内核中的IPC通信整合,方案也可能各不相同,最终看到的现象就是:内核架构形态不一,没有标准,带来的后果就是:

  1. 由于内核架构没有标准化,即使各厂商开源了自家的内核源码,但是,同一个功能,为了适配更多厂商的内核定制化标准,开发人员必须花大量的时间去学习各厂商的内核定制化标准,才能将这个功能接入所有厂商的内核,研发成本很高。
  2. 如果有些厂商关注网络性能场景,那么,他把网络通信模块放入内核,但是,没有把文件系统放入内核,那么,可能该操作系统的文件操作的性能就会很差。反之,有些厂商关注文件操作性能,他们把文件系统放入内核,但是,网络通信交由用户自研,那么,结果就是该厂商的操作系统的网络通信性能就差。因此,不同厂商研发的混合内核操作系统应对的场景不同,导致我们想找一个同时保证网络通信和文件操作性能的操作系统不太容易。

因此,MIT的教授提出了外核这个概念,用来解决混合内核操作系统带来的上面两个问题。我们来看看什么是外核?

2022-09-06-13-58-40-image.png

图中,exokernel就是内核,我们发现外核操作系统将IPC、虚拟内存管理、陷入中断及POSIX标准、TCP都放到用户空间,让用户自己实现,我们把它们都定义为应用,内核中只保留安全访问控制,所有应用在操作硬件时只需要经过内核的一次安全访问检查,就可以操作硬件,当然,安全访问规则在内核中,所以,在进行安全访问检查时,还会产生一次内存拷贝,但是,性能还是可控的。通过这样的设计,的确实现了操作系统的高性能、高扩展和标准化,即:

  • 在用户空间和内核空间只需一次拷贝,一定程度提升了应用执行的效率
  • 将IPC、虚拟内存、TCP等原本内核实现的部分交由用户自己实现,大量用户可以参与这部分开发,加速了应用的扩展
  • 只要内核对应用提供标准的接口定义,就可以方便用户按照该标准自研应用

问题

那么,外核结合了高性能、高扩展、标准化的特点,是不是外核操作系统就完美了呢?

2022-09-06-15-13-49-image.png

图中是外核操作系统,其中有两个并发线程,一个线程执行while循环,一个线程通过telnet发送网络数据包,我们发现当CPU在执行while相关指令时(还没执行完),此时另一个线程在网卡发送完数据包后,给CPU发送中断通知,那么,这时候,CPU不得不暂停while循环处理,处理网卡中断。同样,回顾宏内核、微内核、混合内核操作系统,它们在实现数据包发送时,都要处理中断,只是宏内核、微内核、混合内核操作系统的中断处理在内核中实现,外核操作系统的中断处理由用户自定义的库实现,但是都离不开CPU通知。那么,结合上面这个场景,如果有大量并发线程同时发送数据包,那么,CPU就会被网卡频繁打断,while循环将被中断无数次,while循环处理性能大大下降,此时,CPU将会成为并发处理的瓶颈。

因此,我提出了一个新的概念:分布式内核(Distributed kernels),让所有硬件都装上”大脑“,处理自身的中断,用来解决上面的问题。

分布式内核OS架构长什么样?

我们先来看看分布式内核操作系统长什么样?

chanus.001.jpeg

我们先来看下图中的几个核心组件:

Register Center:注册中心,用来存储硬件地址,硬件操作库使用到的buffer地址,硬件操作库访问相关硬件的路由规则,安全访问规则,中断策略等。这些组成了我们的内核。我们将这些信息划分为两类:Security和Scheduler。

NetLib:网络通信库,实现数据包在网卡(NIC)之间传输。

FileLib:文件操作库,实现文件在硬盘上的读写。

Security:安全访问规则,用来控制用户程序对硬件资源的有限访问,该规则存储在注册中心。

Scheduler:硬件操作库访问相关硬件的路由规则及中断策略。例如,NetLib可以通过这个路由规则找到网卡,然后发送数据包,反之,网卡也可以通过这个路由规则找到NetLib的接收buffer,用来缓冲从网卡接收过来的数据包。所有路由规则也是存在注册中心。

kernel:存储了注册中心的所有数据,包括硬件地址,硬件操作库使用到的buffer地址,硬件操作库访问相关硬件路由规则,安全访问规则,中断策略等。

之所以叫做分布式内核,因为内核(kernel)被嵌入到各个硬件中了,而不是集中在内核空间。

如何破解频繁中断的困局?

讲了那么多组件,那么,分布式内核操作系统到底是如何解决上面提到的频繁中断的问题呢?

2022-09-06-16-21-42-image.png

左边是外核操作系统在上面问题场景中处理并发线程的过程,右边是分布式内核操作系统处理相同问题场景的过程,左边的图我之前讲解过了,所以,这里我就讲解右边的图,大家可以对比着看,主要区别有2点:

  1. while循环处理不再经过内核,即注册中心,而是直接调用CPU中的内核(kernel)检查CPU访问权限,然后由CPU执行循环指令。
  2. telnet命令同样不再经过内核,直接调用网卡(NIC)中的内核(kernel),然后,由内核中的中断控制器(IC)来处理网卡发送完数据包后的中断通知。

我们发现流程中取消了给CPU发送中断通知的步骤,转由网卡内部的kernel中的中断控制器监听网卡发送情况,当数据包发送完成,通知该控制器。中断控制从CPU转移到了硬件,这样做有什么好处呢?

当我们把中断控制权从CPU转移到各个硬件,把同类操作的中断打散到不同硬件中处理,避免CPU这种集中式的中断处理,释放出CPU资源,去执行更有价值的指令,提升CPU及其他硬件的利用率,同时,也减少了中断上下文切换。

比如,上面的问题场景,CPU执行while循环指令和网卡中断可以并行执行了,互相不影响,提升了系统并发处理能力。

如果大家注意看上面的流程,我把安全访问CPU的规则放到了硬件的内核里,那么,如果有用户程序要访问CPU资源,就可以绕过内核空间,直接到CPU中检查权限,避免了system_call这种用户态和内核态切换的中断开销,提升了硬件操作的效率。

同时,内核空间的所有信息都被打散到硬件和硬件操作库,真正实现了内核无状态的无限水平扩展。

kernel、中断控制器哪里来?

那么,可能有人会问:硬件中内嵌的kernel和中断控制器哪里来?

我们回到上面的分布式内核操作系统架构图,图中有两个flow:register flow和push flow,我就用它们来解释这个问题。

在操作系统启动阶段,会执行这几个步骤:

  1. 将各硬件(包括CPU、硬盘、内存、网卡等)地址注册到内核空间的注册中心
  2. 将硬件操作库(比如:NetLib、FileLib等)使用到的用户空间buffer地址注册到内核空间的注册中心
  3. 注册中心通过分析注册的信息,将安全访问规则及硬件操作库使用到的用户空间buffer地址,中断策略push给硬件,其中,每个硬件要实现中断控制器来接收并存储中断策略。由于这些推送信息包含了Security和Scheduler,所以,我们就把这些信息叫做kernel
  4. 注册中心将硬件地址push给硬件操作库

当系统启动完,每个硬件就有了kernel,以及kernel中的中断控制器。

分布式内核OS有什么优势?

讲了那么多,那我们来归纳一下分布式内核操作系统相比集中式内核操作系统(宏内核、微内核、混合内核、外核)到底有什么优势?

  • 中断策略被打散到各硬件,避免了CPU成为中断处理的瓶颈,提升了系统并发处理能力
  • 安全访问规则被打散到各硬件中,避免的用户态和内核态的中断切换,提升了硬件操作的性能。
  • 内核空间的所有信息都被打散到硬件和硬件操作库,真正实现了内核无状态的无限水平扩展。

我们需要做什么?

最后,通过对分布式内核操作系统的剖析,我们发现要真正实现一个分布式内核操作系统,还是有很多基础工作要做,比如:

  • 制定所有硬件接收kernel,以及中断控制器的标准
  • 路由规则、安全访问规则、中断策略如何转化为指令推送给硬件和硬件操作库

结束语

我设计分布式内核OS的初衷,希望从最底层重建操作系统内核理论和架构,为内核的发展出一份来自中国的力量!也希望全球更多的人看到它,一起推动它走向操作系统内核之巅!