鸿蒙轻内核源码分析系列一 前言
鸿蒙轻内核源码分析系列一 前言
1 鸿蒙轻内核概述
鸿蒙轻内核是基于面向IoT
领域构建的Huawei LiteOS
轻量级物联网操作系统内核演进发展的新一代内核。鸿蒙轻内核提供了小体积、低功耗、高性能、快速互联体验、生态统一开放的系统能力,新增了丰富的内核机制、更加全面的POSIX
标准接口以及统一驱动框架HDF(OpenHarmony Driver Foundation)等,为设备厂商提供了更统一的接入方式,为OpenHarmony的应用开发者提供了更友好的开发体验。
鸿蒙轻内核具有如下五大优势:
-
小体积:内核组件轻量化设计,可根据业务需求,在128K到512M灵活配置伸缩。
-
低功耗:低功耗超长待机(Tickless、Run-Stop智能休眠技术),典型场景下功耗从mA降到uA级。
-
高性能:快速启动系统,百ms级冷启动抓拍到图像。
-
快速互联体验:提供分布式软总线、分布式设备安全连接基础互联协议,方便生态设备接入。
-
统一开放生态:兼容三方库和生态圈,兼容CMSIS、POSIX接口,三方库可平滑移植;提供统一的设备驱动框架HDF,方便外设Sensor、器件等驱动开发集成;提供可视化集成开发工具(IDE),实现一站式产品集成、应用开发。
2 鸿蒙轻内核开源介绍
OpenHarmony
是开放原子开源基金会(OpenAtom Foundation
)旗下开源项目,定位是一款面向全场景的开源分布式操作系统。开源站点是https://gitee.com/openharmony。
本源码分析专题系列,计划对OpenHarmony
的轻量系统、小型系统的内核源码进行详细的分析,帮助开发者更好的理解内核运行机制,更好的掌握内核开发。分析时所涉及的源码,均可以在开源站点获取: 轻量系统 kernel_liteos_m代码仓 、小型系统 kernel_liteos_a代码仓。为了更容易找到鸿蒙轻内核代码仓,建议关注Watch
、收藏点赞Star
、并Fork
到自己账户下。有任何问题、建议,都可以留言给我们,欢迎反馈问题、贡献代码。
3 鸿蒙轻内核源码分析系列大纲
鸿蒙轻内核源码分析系列,首先会盘点下重要的数据结构,包含双向链表、就绪队列、排序链表等。会结合数据结构相关绘图,剖析下据结构及其操作的源代码,帮助更好的学习和理解这些数据结构的用法。分析完数据结构,会给后续源码分析奠定基础,接下来会分析中断模块、时间管理模块的源代码。然后分析操作系统非常重要的任务模块、任务调度模块。分析完毕任务和调度模块后,会分析负责任务间通信的互斥锁、信号量、消息队列模块。最后是软件定时器和内存管理模块。
建议开发者,结合源码分析系列的讲解,参考官方示例程序代码,动手写写程序,实际编译运行一下,看到运行效果,加深对鸿蒙轻内核的理解。
3.1 数据结构-双向链表
双向链表Doubly Linked List
是鸿蒙轻内核最重要的数据结构之一,在各个模块有着非常广泛的使用。双向链表是指含有往前和往后两个方向的链表,每个结点中存放下一个节点指针,和一个指向前一个节点的指针。从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式能方便地完成查找、插入、删除等操作。通过分析双向链接提供的接口源代码,深入掌握双向链表的使用,在分析内核其他模块源代码时,更加容易理解。开发者开发自己的用户程序时,也可以灵活的使用双向链表。
3.2 数据结构-就绪队列
在鸿蒙轻内核任务调度模块,就绪队列是个重要的数据结构,能够高效、方便的支持任务基于优先级进行调度。任务创建后,状态设置为就绪态,并放入就绪队列。在实现上,就绪队列是一个双向循环链表数组,每个数组元素就是一个对应任务优先级的链表,相同优先级的任务放入同一个链表。任务就绪队列Priority Queue
主要供内核模块内部使用,用户进行业务开发时不涉及,所以并未对外提供接口。通过分析就绪队列数据结构及其操作接口源代码,可以更容易学习、掌握任务接口、任务调度模块。
3.3 数据结构-排序链表
鸿蒙轻内核的任务排序链表,用于任务延迟到期/超时唤醒等业务场景,是一个非常重要、非常基础的数据结构。任务排序链表是一个环状的双向链表数组,双向链表的头结点,指向双向链表数组的第一个元素,维护游标信息,记录当前的位置信息。每过一个Tick
,游标指向数组下一个位置。数组元素是个双向链表,链表节点维护索引和滚动数信息。当运行到的数组位置挂载的双向链表不为空时,则把第一个节点维护的滚动数减1。这样的数据结构类似钟表表盘,也称为时间轮
。掌握排序链表这一重要的数据结构,会给进一步学习、分析源代码奠定基础,让后续的学习更加容易。
3.4 中断管理
中断是指出现需要时,CPU暂停执行当前程序,转而执行新程序的过程。当外设需要CPU
时,将通过产生中断信号使CPU
立即中断当前任务来响应中断请求。通过中断机制,在外设不需要CPU
介入时,CPU
可以执行其它任务,而当外设需要CPU
时,将通过产生中断信号使CPU
立即中断当前任务来响应中断请求。这样可以使CPU
避免把大量时间耗费在等待、查询外设状态的操作上,有效提高系统实时性以及执行效率。本小节会掌握中断相关的概念,剖析鸿蒙轻内核的中断模块的中断初始化操作,中断创建、删除,开关中断操作等源代码。
3.5 时间管理
时间管理模块以系统时钟为基础,可以分为两部分,一部分是SysTick
中断,为任务调度提供必要的时钟节拍;另外一部分是,给应用程序提供所有和时间有关的服务,如时间转换、统计功能。
系统时钟是由定时器/计数器产生的输出脉冲触发中断产生的,一般定义为整数或长整数。输出脉冲的周期叫做一个“时钟滴答”,也称为时标或者Tick
。Tick
是操作系统的基本时间单位,由用户配置的每秒Tick
数决定。另外一个计时单位是Cycle
,这是系统最小的计时单位。Cycle
的时长由系统主时钟频率决定,系统主时钟频率就是每秒钟的Cycle
数。用户以秒、毫秒为单位计时,而操作系统以Tick
为单位计时,当用户需要对系统进行操作时,例如任务挂起、延时等,此时可以使用时间管理模块对Tick
和秒/毫秒进行转换。本小节会剖析鸿蒙轻内核的时间管理模块的源代码。
3.6 任务和任务调度
任务是操作系统一个重要的概念,是竞争系统资源的最小运行单元。任务可以使用或等待CPU
、使用内存空间等系统资源,并独立于其它任务运行。任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。任务调度也是操作系统的一个重要模块,它负责选择系统要处理的下一个任务。调度模块需要协调处于就绪状态的任务对资源的竞争,按优先级策略从就绪队列中获取高优先级的任务,给予资源使用权。本文我们来一起学习下任务和任务调度模块的源代码,包含任务栈初始化,任务上下文,任务初始化,任务常用操作接口,任务调度函数的源代码。
3.7 互斥锁
多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,只能被独占使用。鸿蒙轻内核使用互斥锁Mutex
来避免这种冲突,互斥锁是一种特殊的二值性信号量,用于实现对临界资源的独占式处理。用互斥锁处理临界资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个临界资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此可确保同一时刻只有一个任务正在访问这个临界资源,保证了临界资源操作的完整性。本小节会分析下互斥锁模块的源代码。
3.8 信号量
信号量(Semaphore
)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数。本小节通过详细分析信号量模块的源码,帮助更好的掌握信号量的使用。
3.9 队列
队列(Queue
)是一种常用于任务间通信的数据结构。任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。如果将读队列和写队列的超时时间设置为0,则不会挂起任务,接口会直接返回,这就是非阻塞模式。消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用。本小节通过分析队列模块的源码,帮助更好的掌握队列的使用。
3.10 事件
事件(Event
)是一种任务间通信的机制,可用于任务间的同步。多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。本小节通过分析内核事件模块的源码,帮助深入掌握事件的使用。
3.11 定时器
软件定时器(Software Timer
)是基于系统Tick
时钟中断且由软件来模拟的定时器。当经过设定的Tick
数后,会触发用户自定义的回调函数。硬件定时器受硬件的限制,数量上不足以满足用户的实际需求。鸿蒙轻内核提供的软件定时器功能可以提供更多的定时器,满足用户需求。本小节通过分析定时器模块的源码,帮助开发者更好的掌握定时器的使用。
3.12 静态内存
内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放。在系统运行过程中,内存管理模块通过对内存的申请/释放来管理用户和OS
对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统的内存碎片问题。鸿蒙轻内核的内存管理分为静态内存管理和动态内存管理。
静态内存模块,支持在静态内存池中分配用户初始化时预设的固定大小的内存块,分配和释放效率高,静态内存池中无碎片。只能申请到初始化预设大小的内存块,不能按需申请。本小节主要分析静态内存(Memory Box
)模块的源代码,帮助开发者更深入的掌握静态内存的使用。
3.13 动态内存
动态内存管理模块主要用于用户需要使用大小不等的内存块的场景。当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。可以按需分配,缺点是内存池可能出现碎片。本小节主要分析动态内存模块的源代码,介绍动态内存分配算法,帮助开发者更深入的掌握动态内存的使用。
感谢阅读,有任何问题和建议,请给我们留言。
- 点赞
- 收藏
- 关注作者
评论(0)