来源丨51CTO技术栈(ID:blog51cto)
众所周知,HarmonyOS具备分布式软总线、分布式数据管理和分布式安全三大核心能力。多种设备之间能够实现硬件互助、资源共享,依赖的关键技术。同时还实现了包括分布式软总线、分布式设备虚拟化、分布式数据管理、分布式任务调度等功能。在被这些眼花缭乱的功能的环绕之下,我们往往忽视了鸿蒙的内核技术,HarmonyOS采用多内核设计,支持针对不同资源受限设备选用适合的OS内核。由于HarmonyOS需要对不同的硬件资源进行适配,因此需要内核具备灵活性、可扩展性,可靠性和可移植性,同时还需要对分布式系统的支持,因此微内核的应用就成了HarmonyOS的首选。今天就带大家了解微内核,以及它在HarmonyOS中的应用。
和其他操作系统类似,鸿蒙OS整体遵从分层设计,如图1所示,从下往上依次为内核层、系统服务层、框架层和应用层。系统功能按照“系统>子系统>功能/模块”逐级展开。在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或功能/模块。图1 鸿蒙OS技术架构
如图1所示,我们可以看到鸿蒙OS的整体架构,而本文我们需要聚焦内核层的架构体系。内核层由内核子系统和驱动子系统组成。内核子系统:鸿蒙OS采用多内核设计,支持针对不同资源受限设备选用适合的OS内核。内核抽象层(Kernel AbstractLayer,KAL)通过屏蔽多内核差异,对上层提供基础的内核能力,包括进程/线程管理、内存管理、文件系统、网络管理和外设管理等。驱动子系统:硬件驱动框架(HDF)是鸿蒙OS硬件生态开放的基础,提供统一的外设访问能力、驱动开发及管理框架。而在内核子系统中包含了LiteOS的内核就是今天的主角,也就是我们要提到的微内核,为什么鸿蒙OS在具备Linux Kernel的情况下还要引入LiteOS的微内核技术作为补充呢?接下来就让我们一起走进微内核的世界。
在描述微内核之前,要了解什么是内核。大家都知道计算机是由诸多硬件组成的,包括:CPU、内存、磁盘、网卡、显示器、键盘、鼠标等等。为了能够管理和组织这些硬件资源,我们创造操作系统,而内核就是操作系统中的核心部分。就好像我们常用的Windows操作系统,Unix以及Linux操作系统,它们都存在内核。而目前市面上、绝大多数操作系统都是宏内核,其典型代表就是Linux。宏内核中的“宏”字表现为,将内核服务作为整体,所有服务都“伸手即得”。也就是将控制计算机的各个模块,都聚合在内核中方便管理。如下图2所示,CPU调度、文件系统、内存管理、应用管理调度、中断处理、设备驱动都放在内核中。如果应用程序需要申请内存,内核直接使用“内存管理”给应用分配内存,使用“应用管理进程调度”给应用分配进程,没有额外的消耗。宏内核的这种处事方式就好像一个公司将所有的职能部门都拉到一个办公室办公,这个办公室有好多张桌子每个桌子上面都有各个职能部门的办事员,操作系统要处理什么事情都通过宏内核这个大办公室来解决,因此解决问题是很高效的。但是问题也很明显,随着系统的不断发展,内核中会加入各种不同的模块,就好像大办公室需要更多的桌子,从而坐下更多的人。内核中模块不断增大,就需要更高的硬件资源来支持,同时模块的增多也带来了系统复杂性的增加,提高了系统崩溃的风险,例如内核中有一个模块挂了会导致整个内核的崩溃。为了解决宏内核所面临的问题,就推出了微内核的概念, 微内核是内核的一种精简形式。它将与宏内核集成在一起的系统服务分离出去,让这些服务模块变成按需加载,也就是把这些服务变成可选项而非必选项,如果需要这些服务就作为内核的一种扩展。如果需要对系统内核进行升级,只要用新模块替换旧模块,或者在原有服务的基础扩展新的服务。这样就不需要改变整个操作系统的内核。
如图3所示,微内核与宏内核的区别在蓝色的部分,微内核将宏内核蓝色部分的系统服务进行拆解,将一些重要的服务依旧留在内核中,例如:进程间通信、虚拟内存、进程调度等。而将其他服务放到了内核之外,这些服务直接在用户态运行,内核态的一些核心服务会和这些被剥离的服务进行交互,保证进程间的通信。同时,这些用户态的服务会直接服务于应用程序。如果将图3进行化简就得到了图4, 如图4所示,在宏内核的时代所有的服务都在内核中,内核中的服务为应用提供服务,而到了微内核时代,将一些服务从内核移到了外边,这些被移出去的服务依旧与内核中的核心服务保持联系,同时为应用服务。微内核结构使用一个水平分层代替传统的纵向分层,所有微内核之外的操作系统构件都被当作服务进程来实现,它们可以通过微内核传递消息来实现相互之间的交互。因此,微内核还可以验证消息并授权访问硬件,而且微内核还执行保护功能,阻止非法的信息等。例如,应用程序如果要打开一个文件,则它发送消息给文件系统服务,如果他想创建一个进程或线程,则它发送消息给进程服务进程。每个服务进程之间可以相互通信,并可以调用微内核中的功能。
按照图4的操作,微内核包含的服务数会减少,实现服务的代码量也会有明显的下降。微内核尽可能简化内核,将更多的用户服务程序放置在内核之外完成。内核仅仅放置最核心以及经常性需要使用到的程序代码。如果还是用办公室来打比方,微内核将大办公室缩小了,将其中一些办公桌移到了办公室外边,在大办公室之外设置了多个小办公室安置这些办公桌。在大办公室内只安放重要的核心的服务,用来管理和协调小办公室的工作。鸿蒙OS在发布会上强调了多个特性用来强调鸿蒙OS作为一个操作系统而言本身的突破和优势在哪里,实际上在使用微内核以后鸿蒙OS具备下面四点能力的提升:- 基于微内核技术的可信执行环境,通过形式化方法提升了内核安全,全面提升全场景终端设备的安全能力。
- 鸿蒙OS可支撑开发者实现一次开发、多端部署,最终实现跨终端生态共享。
上面我们介绍了什么是微内核,以及宏内核与微内核的区别,下面来看看微内核具备哪些优点。- 提供一致的接口:进程不用区分内核服务还是用户服务,并且都是通过消息传递;
- 可扩展性:当需要增加新的服务时,只需要增加新的服务进程,而不需要修改内核;
- 灵活性:可以定制服务进程,例如分布式系统需要增加安全性相关的服务进程;
- 可移植性:大部分处理器专用代码在微内核中,如果需要移植到另一个处理器上时,只需要修改少量的代码;
- 可靠性:足够小的微内核能够进行充分的测试,从而提供更稳定的代码。只提供少量的API和交互方式,减少组件之间的相互影响;
- 分布式系统的支持:如果一个客户往一个服务进程发送消息时,该消息包含请求服务的标识符。在分布式系统被配置为所有进程和服务都具有唯一的标识符,微内核会为这类标识符提供单独的系统映像,让进程消息发送透明化;
- 适用于面向对象设计:微内核设计和操作系统模块化的开发都可以借助面向对象的原理。例如,一种方式是构造组件,组件间通过组建接口交互,它们可以通过搭积木的方式构件软件。
前面提到了鸿蒙OS使用了微内核提升操作系统的灵活性、可扩展性,可靠性和可移植性,为分布式系统的设计提供支撑。接下来就来看看LiteOS
的内核是如何实现微内核的。在文章的第一个部分就提到了在鸿蒙OS的内核子系统中就实现了LiteOS,LiteOS是华为面向物联网领域开发的一个基于实时内核的轻量级操作系统。它支持任务管理、内存管理、时间管理、通信机制、中断管理、队列管理、事件管理、定时器等操作系统基础组件,更好地支持低功耗场景,支持tickless机制,支持定时器对齐。
任务管理
任务是竞争系统资源的最小运行单元。LiteOS支持多任务运行,一个任务就表示一个线程,任务之间可以进行切换和通信。LiteOS的任务管理模块提供任务创建、删除、延时、挂起和恢复、更改任务优先级、锁定任务调度和解锁任务调度、根据任务控制块查询任务ID、根据ID查询任务控制块信息等功能。LiteOS使用抢占式调度内核,高优先级的任务可以打断低优先级任务,同优先级任务会进行时间片轮转调度。同时,每一个任务都含有一个任务控制块(TCB),它包含了任务的所有状态和运行信息。T具体包括:上下文栈指针(stack
pointer)、任务状态(包括就绪、运行、阻塞、退出4种状态)、任务栈大小(任务栈里保存着局部变量、寄存器、函数参数、函数返回地址等)、任务优先级、任务ID、任务名等信息。在任务服务初始化时,会先申请TCB需要的内存空间。任务初始化完成,则系统对TCB内容进行初始化。用户创建任务时,系统会将任务栈进行初始化,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。
内存管理
LiteOS的内存管理模块管理系统的内存资源,主要包括内存的初始化、分配及释放。其目的是管理用户和OS对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统的内存碎片问题。LiteOS的内存管理分为动态内存管理和静态内存管理。
动态内存管理
静态内存管理
在静态内存池中分配用户固定(预设配置)大小的内存块。
中断管理
在LiteOS中,用户可以通过中断申请,注册中断处理程序,并且指定CPU响应中断请求时所执行的具体操作。避免CPU把大量时间耗费在等待、查询外设状态的操作上,因此将大大提高系统实时性以及执行效率。按照硬件可以对中断划分为三类:设备、中断控制器、CPU本身。- 设备:发起中断的源,当设备需要请求CPU时,产生一个中断信号,该信号连接至中断控制器。
- 中断控制器:中断控制器是CPU众多外设中的一个,它一方面接收其它外设中断引脚的输入,另一方面,它会发出中断信号给CPU。可以通过对中断控制器编程实现对中断源的优先级、触发方式、打开和关闭源等设置操作。
- CPU:CPU会响应中断源的请求,中断当前正在执行的任务,转而执行中断处理程序。
信号量管理
信号量(Semaphore)是一种实现任务间通信的机制,可以用于任务之间同步或临界资源的互斥访问。
如图5所示,信号量可以被任务线程获取,不同的信号量通过信号量索引号来唯一确定,每个信号量都有一个计数值和任务队列。通常信号量的计数值表示有效的资源数,即剩下的可被占用的互斥资源数。当任务申请(Pend)信号量时,如果申请成功,则信号量的计数值递减,如申请失败,则挂起在该信号量的等待任务队列上,一旦有任务释放该信号量,则等待任务队列中的任务被唤醒开始执行。
图 5 信号量运作示意图
上面提到了信号量的使用方式,由于它是对资源使用量的计数器,因此以下两个场景经常会出现信号量的身影。
任务互斥:当多个任务同时对一个临界资源进行访问时,会对这个资源维护一个信号量,初始值为1,当有任务线程访问时就将这个值减1,此时如果其他任务线程也访问该资源会先检查信号量,如果小于等于0就等待。当之前的任务线程访问完毕,释放资源时会将信号量加1,此时其他任务线程就可以访问该资源了。
资源计数:用于生产者与消费者的场景可以通过信号量的递增或者递减来表示资源的状态。
本文从鸿蒙OS的架构特性入手,发现在内核子系统中使用了LiteOS的微内核架构,从而引出了微内核在鸿蒙架构中扮演的特殊角色。为了解释什么是微内核,先从操作系统内核说起,接着介绍了常见的宏内核将所有服务都集于一身,微内核为了提升灵活性、可扩展性,可靠性和可移植性,将一些非核心的服务从内核中剥离,只留一些核心服务在内核中减少了内核的容量,降低了出错的风险。最后,又回到开始时介绍的LiteOS
,并介绍了它的四大核心模块,包括:任务管理、内存管理、中断管理以及信号管理。
作者介绍
崔皓,51CTO社区编辑,资深架构师,拥有18年的软件开发和架构经验,10年分布式架构经验。曾任惠普技术专家。乐于分享,撰写了很多热门技术文章,阅读量超过60万。《分布式架构原理与实践》作者。
Excel永远不会消亡!
在7年跑了6个程序员后,开发商找来零基础的粉丝做游戏
还在用U盘拷文件?老手都在用的进阶方法了解一下
一件程序员才懂的T恤