2.3 多内核嵌入式操作系统和虚拟机
多内核嵌入式操作系统指有多个内核的嵌入式操作系统。这些内核同时在硬件平台上面运行,共同管理着系统中的软件和硬件资源。多内核的嵌入式操作系统按照其组织结构可以分为两类:一类叫做一体化结构的多内核嵌入式操作系统,另一类叫做基于虚拟机的多内核嵌入式操作系统。
2.3.1 为什么要引入多内核嵌入式操作系统和虚拟机
实际应用有时会对嵌入式操作系统提出一些多元化的需求(如有非常强的实时性能;能在资源极为有限的硬件平台上运行;可以运行基于Linux系统开发的应用软件),使得现有的任何一种嵌入式操作系统都不能直接满足这些需求。解决这个问题的方法通常有两种:一种是新开发一种功能更强的嵌入式操作系统;另一种是将两个甚至多个嵌入式操作系统组合在一起,通过相互弥补不足的方式满足应用需求。第一种方法看似直截了当,但受很多因素的制约,实际上往往行不通。例如,使用者对现有的操作系统已经非常习惯,难以舍弃;现有操作系统的研发者出于商业利益的考虑,暂时不愿意开发新的系统;开发新操作系统所需的某种关键技术未得到解决等。所以在很多情况下还是选择第二种解决方法。这就是为什么要引入多内核嵌入式操作系统的原因。
当多个嵌入式操作系统在同一个硬件平台上运行时,必然出现如何协调各操作系统之间关系的问题。这有两种解决方法,一种是由各操作系统自己解决相互协调的问题,另一种是由一个位于硬件之上,操作系统之下的独立功能模块来解决相互协调的问题。这个位于硬件之上,操作系统之下的独立功能模块就是所谓的虚拟机。
对嵌入式操作系统的多元化需求,适合采用多内核嵌入式操作系统予以解决,下面来看两个比较典型的实例。
第一个实例来自于智能手机。智能手机相当于普通手机与PDA的融合。在它的CPU上面既要运行通信处理软件,也要运行普通PDA软件(如个人信息管理软件)。因此对智能手机上的操作系统提出了两个不同的需求。从通信处理的角度出发,要求操作系统有很强的实时处理能力。从便于PDA应用软件开发和移植的角度出发,要求操作系统应当与Linux甚至更多的常用嵌入式操作系统兼容。这两个需求是相互矛盾的,很难在基于一个嵌入式操作系统的前提下解决,但采用一个双内核的嵌入式操作系统就能够比较好地解决这一问题。在这个双内核嵌入式操作系统中,一个内核有很强的实时性能,可用于支持通信方面的实时任务。另一个则是Linux的内核,可以支持非实时的应用任务,大量符合POSIX标准的应用程序几乎不加修改地就可以在这个内核上运行。
第二个实例来自于无线传感网。在无线传感网中有微传感器和网关两类网络结点。微传感器的资源极为有限,因此运行于微传感器上的嵌入式操作系统所占内存应当非常小,对微处理器的要求应当非常低。当然,需要这种嵌入式操作系统提供的功能也不是很复杂,都是一些支持任务运行所必需的功能。相对微传感器而言,网关结点的资源丰富得多。它的主要功能是将由微传感器所组成的网络接入其他网络,如GSM的无线蜂窝网。网关结点通常还可以提供其他一些功能,如网络管理功能,甚至充当一般的微传感器。因此网关上的操作系统要比微传感器上的操作系统有更强的功能。对于微传感器和网关之间的这种差别,一种解决办法是在微传感器和网关上分别采用不同的嵌入式操作系统,但这显然不是一个好的解决方案,对无线传感网应用软件的开发和移植都有不良的影响。还有一种方案是在微传感器上采用一种功能精简的嵌入式操作系统,而在网关上采用一个双内核的嵌入式操作系统,其中一个内核与运行在微传感器上的操作系统内核相同,另一个操作系统内核则功能较强,可以支持复杂应用。
2.3.2 一体化结构多内核嵌入式操作系统原理与组成
一体化结构的多内核嵌入式操作系统由同在一个硬件平台上运行的内核自己解决相互协调的问题。理论上,在一个硬件平台上虽然可以同时运行多个嵌入式操作系统内核,但实际中使用的一般都是双内核系统。这种双内核嵌入式操作系统的典型用途是弥补嵌入式Linux操作系统在实时性方面的缺失。RTLinux和RTAI是这种双内核操作系统的典型代表。它们都是把Linux内核与一个实时内核合并在了一起。
如图2.38所示,这种双内核操作系统的原理是将Linux内核(也可以是其他某种实时性较低的操作系统内核)作为实时内核的一个低优先级任务。系统中的任务被分为了实时任务和非实时任务两类,实时内核调度和处理实时任务,Linux内核调度和处理非实时任务。由于Linux内核是实时内核的一个优先级最低的任务,所以只有当系统中没有实时任务时,Linux内核才可能被运行,并开始处理系统中的非实时任务,因此实时任务总是能够优先得到运行。通过这种简单的方法,双内核操作系统在保证实时性的前提下实现了两个操作系统内核的融合。
图2.38 一体化结构的双内核嵌入式操作系统的组成
当有中断请求到来时,由虚拟中断管理模块负责接收,并按先实时内核后Linux内核的次序,将中断请求传递给两个操作系统内核,使两个操作系统内核都有机会按照自己方式对中断进行处理。(RTLinux中没有虚拟中断管理模块,它将该模块承担的功能合并到了实时内核中。所以在RTLinux中,当有中断请求到来时,是由实时内核负责接收,并对其进行处理,然后再传递给Linux内核。)
一体化结构的多内核嵌入式操作系统有以下5个特点。
① 在保留原有操作系统内核构架的前提下,实现多个内核的有机融合,使它们可以相互配合工作,发挥各自的优势,向应用软件开发者提供一个功能更强的操作系统。
② 操作系统内核间的协调、通信等问题由各个内核自己解决。
③ 系统采用主次的结构,多个操作系统内核的地位不平等。系统一般以一个操作系统内核为主,由它负责一些管理性的工作,如操作系统内核间的通信。
④ 系统的层次关系及其各操作系统内核间的接口不清晰,因此在采用一体化结构将多个嵌入式操作系统组合在一起形成一个多内核嵌入式操作系统时,需要根据具体情况对原有的操作系统内核做比较多的修改和调整,这给系统的维护带来了一定麻烦。有时这种修改和调整所产生的变化甚至会影响到应用软件的开发。
⑤ 实时任务在核心态运行,给操作系统的稳定性带来了一定隐患。多内核操作系统将非实时内核(如嵌入式Linux的内核)作为实时操作系统内核的一个低优先级任务。这种做法虽然简化了系统设计,但是由于非实时内核必须在核心态运行,所以迫使所有的实时任务也要在核心态运行。实时任务作为一种应用程序,出错可能性远高于操作系统代码,因此降低了系统的稳定性。
2.3.3 虚拟机的原理与组成
虚拟机是在一体化结构多内核嵌入式操作系统的基础上发展起来的一种技术。一体化结构的多内核嵌入式操作系统存在着内核间的接口不清晰、系统的稳定性存在隐患等问题。虚拟机的引入在很大程度上解决了这些问题。
如图2.39所示,虚拟机是一个直接位于硬件之上的底层软件。在虚拟机之上可以运行多个嵌入式操作系统内核(虽然在实际中使用较多的也是双内核的系统)。这些内核和虚拟机一起共同组成了一个基于虚拟机的多内核嵌入式操作系统。虚拟机提供支持在同一个硬件平台上运行多个操作系统内核所需的一系列功能模块。主要包括虚拟中断管理模块、虚拟管道模块、内存管理模块3个功能模块。除此之外,原来硬件抽象层所具有的功能也应被包括在虚拟机之中。
图2.39 基于虚拟机的多内核嵌入式操作系统的组成
1. 虚拟中断管理模块
虚拟中断管理模块对来自计算机硬件的中断请求进行处理。它提供了保障多个操作系统内核同时在一个硬件平台之上运行所需要的最基本功能,使多个操作系统内核可以独立运行、互不影响。如图2.40所示,虚拟中断管理模块自底向上可以划分硬件监控层、中断分发层、内核服务层3个层次。硬件监控层监听来自硬件的中断请求。中断分发层按照优先级将来自硬件的中断请求发送给运行在虚拟机之上的操作系统内核,并回调操作系统注册的中断服务程序。内核服务层负责中断服务程序的注册、注销和开中断、关中断等项工作。
图2.40 虚拟中断管理模块的结构
如图2.41所示,运行在虚拟机上的操作系统内核有不同的优先级,这个优先级决定了来自硬件的中断请求传给各个操作系统内核的次序。优先级最高的操作系统内核总是最先接收到来自硬件的中断请求,该请求然后依次被传递给运行在虚拟机上的其他操作系统内核。一个操作系统内核可以选择是否接收和处理某种中断请求。有一些中断请求,如时钟中断,所有的操作系统内核必须接收和处理,但某些中断请求可能仅与某个操作系统有关系,所以其他的操作系统内核就不必对其进行接收和处理,这样可以减少许多不必要的工作。一个操作系统内核如果接收和处理某种中断请求,虚拟中断管理模块就会调用这个操作系统的中断服务程序,并在处理结束之后,将该中断请求向下传递,直至到达优先级最低的操作系统内核。
图2.41 中断请求按优先级在各操作系统内核间传递
2. 虚拟管道管理模块
虚拟管道管理模块用于解决多个操作系统内核间的通信问题。它所支持的功能主要是供运行在虚拟机上的嵌入式操作系统内核使用,但在某些时候也可以被应用任务所使用,以便和其他操作系统中的任务相互通信。一体化结构的多内核嵌入式操作系统中一般有某个操作系统内核起主导作用,不同内核之间的通信由它来负责,因此不需要用一个专门的功能模块来解决多个内核间的通信问题。
虚拟管道管理模块的API接口目前尚未标准化,可以采用很多方式。Socket接口和专用设备是两种可行的方式,它们都比较好地解决了与现有编程习惯的兼容问题。Socket接口方式是标准Socket接口的扩充。标准Socket接口规定:在调用Socket函数准备建立通信连接的时候,须给出3个参数,其中一个参数用于指明通信协议。为了支持虚拟管道,可在Socket支持的原有通信协议之外再扩充一种与虚拟管道相对应的协议,使用这种协议建立通信连接就可以通过虚拟管道与其他操作系统相通信。专用设备方式的原理是用一种设备代表虚拟管道。对这种设备可以像其他设备一样进行打开、关闭、读、写等各种操作。这样,使用虚拟管道进行通信的双方只要一方向该设备写入数据,另一方从该设备读出数据就可以达到相互通信的目的。
3. 内存管理模块
内存管理模块用于处理在一个硬件平台之上同时运行多个操作系统内核时在内存管理方面所产生的问题。当多个操作系统内核运行于一个硬件平台上时,必须妥善地解决内存管理问题,否则就不可避免地发生混乱。但解决这个问题并不总是依靠虚拟机中的内存管理模块。按照是否需要由内存管理模块参与解决内存管理,可以把解决内存管理问题的方法分为两类:一类是由内存管理模块解决或帮助解决内存管理问题,另一类则完全是由各操作系统内核自己解决内存管理问题,不需要依靠内存管理模块。
在采用第一类方法解决内存使用问题时,并不是由内存管理模块完全接管内存的管理工作。它所起的作用只是让各操作系统内核中的内存管理功能能够互不干扰地正常工作。例如,若一个多内核操作系统采取的内存管理方案是把物理内存按照一定的比例分配给各个操作系统,由各操作系统分别管理分配给自己的物理内存。那么在进行操作系统内核切换时就需要由内存管理模块对MMU中的页表进行刷新或进行局部的修改。
在采用第二类方法解决内存的管理问题时,内存管理模块的功能完全退化,虚拟机中的内存管理模块实际上已不存在。这类方法的共同特点是解决内存管理问题的措施都与各操作系统所采用的具体内存管理技术密切相关。Hopen双内核操作系统采用的就是这类方法。下面来看该操作系统的内存管理方案。
Hopen双内核操作系统是Hopen操作系统系列产品中的一个成员。它的两个内核分别是Hopen-RT操作系统内核和嵌入式Linux操作系统内核。Hopen-RT是一个实时性很强的嵌入式操作系统,它可以弥补嵌入式Linux在实时性方面的不足。
如图2.42所示,在32位的计算机中有4GB的虚拟地址空间。嵌入式Linux将这4GB的地址空间分成了两部分。低地址的3GB(从虚拟地址0X0至0XBFFFFFFF)作为各任务的用户空间。高地址的1GB(从虚拟地址0XC0000000~0XFFFFFFFF)作为操作系统内核所用的空间,即系统空间。当一个任务通过系统调用进入内核之后,也在系统空间中运行。
图2.42 嵌入式Linux操作系统虚拟地址空间的划分
如图2.43所示,为了解决双内核共同运行时的内存管理问题,Hopen双内核操作系统将Linux任务的用户空间压缩到了0~2GB(从虚拟地址0X0~0X7FFFFFFF)。减少1GB的用户空间对任何Linux任务都不会产生不良影响。节省出来的1GB地址空间没有给Linux内核使用,而是给了Hopen-RT的实时任务。Hopen-RT为每个实时任务提供32MB的用户空间,并且最多可支持20个实时任务同时运行。这样一共需要640MB的地址空间。剩余的384MB的地址空间留给了共享库。在Linux操作系统中1GB的地址空间虽然不归Linux内核使用,但被映射到系统空间中。在Hopen-RT操作系统中则是把任务的用户空间映射到这1GB地址空间中某个32MB的区间内。由于系统空间中的内容常驻内存,不会被换进换出,所以大大提高了Hopen-RT实时任务的实时性。
图2.43 Hopen双内核操作系统虚拟地址空间的划分
4. 硬件抽象层模块
硬件抽象层模块之中封装了一般意义上的硬件抽象层应当提供的功能。这些功能的作用是隐藏硬件平台的一些细节,增强操作系统的硬件无关性。