导图社区 OpenHarmony轻量级内核
内核是一人操作系统的运算核心,决定着系统的性能和稳定性。它是基于硬件的第一层软件扩充,提供操作系统的基本功能,是操作系统工作的基础。它负责管理系统的进程、内存、外设驱动程序、支件和网络系统。
编辑于2024-02-08 16:08:42OpenHarmony轻量级内核
概述
内核是一人操作系统的运算核心,决定着系统的性能和稳定性。它是基于硬件的第一层软件扩充,提供操作系统的基本功能,是操作系统工作的基础。它负责管理系统的进程、内存、外设驱动程序、支件和网络系统
LiteOS-M
概述
百K级内存设备
支持内存保护单元
适用于轻量系统
应用于轻量系统,面向的MCU一般股是百K级内存,可支持MPU隔离,业界类似以的内核有FreeRToS或Threadx等
内核概述
LiteOS-M内核架构包含硬件相关层以及硬件无关层, 其中硬件相关层按不同编译工具链、芯片架构分类, 提供统一的HAL(Hardware Abstraction Layer) 接口其他模块属于硬件无关层, 其中基础内核模块提供基础能力, 扩展模块提供网络、文件系统等组件能力 KAL(Kernel Abstraction Layer)模块提供统一的标准接口
HAL(HardwareAbstractionLayer)接口,提升了硬件易适配性,满足AloT类型丰富的硬件和编译工具链的拓展
内存管理
静态内存
动态内存
通信机制
事件
互锁
消息队列
信号量
CMSIS(Cortex Microcontroller Software InterfaceStandard,微控制器软件接标准) 和 POSIX(Portable Operating System Interface,可移植操作系统接口) 都是可移植操作接口的标准,属于应用接口层,可增强应用软件的可移植性,降低开发难度。
CMSIS(Cortex Microcontroller Software InterfaceStandard,微控制器软件接标准)
CMSIS是对于那些基于ARM Cortex处理器的微控制器独立于供应商的硬件抽象层。它包含多个组件层,其中之一是RTOS层,该层定义了一套通用及标准化的RTOSAPI接口,减少了应用开发者对特定RTOS的依赖,方便用户软件的移植重用。该套API有2个版本,分别为版本1(CMSIS-RTOSv1)和版本2(CMSIS-RTOSv2),OpenHarmonyLiteos-M仅提供其版本2的实现。
POSIX(Portable Operating System Interface,可移植操作系统接口)
OpenHarmony内核使用musl libc库以及自研接口,支持部分标准POsIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。
LiteOS-M内核启动流程
1.在开发板配置文件targetconfig.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置
2.系统后动时,根居配置进行指定模块的初始化
3.内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程
LiteOS-M已经支持ARMCortex-M3、ARMCortex-M4、ARMCortex-M7、ARM Cortex-M33、RISc-V等主流架构
内核基础
任务管理
描述
从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用等待CPU、使用内存空间等系统资源,并独立于其它任务运行
Liteos-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程
任务模块具有如下特性
支持多任务
一个任务表示一个线程
抢占式调度机制
高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度
相同优先级任务支持时间片轮转调度方式
共有32个优先级[0-31],最高优先级为0,最低优先级为31
任务状态
阻塞态(Blocked)包含任务被挂起(suspend状态)、任务被延时(delay状态)、任务正在等待信号量、读写队列或者等待事件等
就绪态->运行态:任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,同时该任务从就绪队列中移出
运行态->就绪态:有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中
就绪态->阻塞态:任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复
阻塞态->就绪态:阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态:此时如果被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态
运行态->阻塞态:正在运行的任务发生阻塞(挂起、延时、读信号量等)时,将该任务插入到对应的阻塞队列中,任务状态由运行态变成阻塞态,然后发生任务切换运行就绪队列中最高优先级任务
运行态->退出态:运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态以及nvalid状态。例如,任务运行结束但是没有自删除,对外呈现的就是lnyalid状态,即退出态
阻塞态->退出态:阻塞的任务调用删除接口,任务状态由阻塞态变为退出态
任务管理相关概念
任务ID
在任务创建时通过参数返回给用户,是任务的重要标识
任务优先级
表示任务执行的优先顺序
任务入口函数
新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置
任务栈
每人任务都拥有一人独立的栈空间,我们称为任务栈。栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等
任务上下文
任务在运行过程中使用的一些资源,如寄存器等,称为任务上下文
任务控制块TCB
每个任务都含有一个任务控制块(TCB)
任务切换
包含获取就绪队列中最高优先级任务、切出任务上下文保存、切入任务上下文恢复等动作
任务开发流程
1.锁任务调度LOs_TaskLock,防止高优先级任务调度。 2.创建任务Los_TaskCreate。 3.解锁任务LOs_TaskUnlock,让任务按照优先级进行调度。 4.延时任务LOs_TaskDelay,任务延时等待。 5.挂起指定的任务Los_TaskSuspend,任务挂起等待恢复操作。 6.恢复挂起的任务Los_TaskResume。
任务管理使用说明
任务管理模块接口
时间管理
描述
以系统时钟为基础
时间管理以系统时钟为基础,给应用程序提供所有和时间有关的服务
系统时钟是由定时器计数器产生的输出脉冲触发中断产生的,一股定义为整数或长整数,输出脉冲的周期叫做一个“时钟滴答”。系统时钟也称为时标或者Tick
操作系统以Tick为单位计时
用户以秒、毫秒为单位计时,而操作系统以Tick为单位计时,当用户需要对系统进行操作时,例如任务挂起、延时等,此时需要时间管理模块对Tick和秒/毫秒进行转换
LiteOS-M内核时间管理模块提供时间转换、统计功能
时间管理单位
Cycle系统最小的计时单位
Cycle的时长由系统主时钟频率决定,系统主时钟频率就是每秒钟的cycle数
Tick是操作系统的基本时间单位,由用户配置的每秒Tick数决定
时间管理不是单独的功能模块,依赖于OS_SYS_CLOCK和LOSCFGBASE_CORE_TICKPERSECOND两个配置选项
系统的Tick数在关中断的情况下不进行计数,故操作系统Tick数不能作为准确时间使用
cycle与tick的关系,cycle是系统内核的计时单位,tick是操作系统的计时单位,两者并不属于同一种计时。用户操作tick即可,cycle一般不操作
LiteOS-M内核中LOSCFG_BASE_CORE_TICK_PER_SECOND默认为100,每秒钟100个tick
时间管理模块接口
中断管理
描述
在程序运行过程中,出现需要由CPU立即处理的事务时,CPU暂时中止当前程序的执行转而处理这人事务,这人过程叫做中断
通过中断机制,在外设不需要CPU介入时,CPU可以执行其它任务:当外设需要CPU时,CPU会中断当前任务来响应中断请求。这样可以使CPU避免把大量时间耗费在等待、查询外设状态的操作上,有效提高系统实时性及热行效率
当硬件产生中断时,通过中断号查找到其对应的中断处理程序,执行中断处理程序完成中断处理
中断管理基本概念
中断号
中断请求信号特定的标志,计算机能够根据中断号判断是哪个设备提出的中断请求
中断请求
“紧急事件”向CPU提出申请(发一个电脉冲信号),请求中断,需要CPU暂停当前执行的任务处理该“紧急事件”,这一过程称为中断请求
中断优先级
为使系统能够及时响应并处理所有中断,系统根据中断事件的重要性和紧道程度,将中断源分为若干个级别,称作中断优先级
中断处理程序
当外设发出中断斯请求后,CPU暂停当前的任务,转而响应中断请求,即执行中断处理程序。产生中断的每个设备都有相应的中断处理程序
中断触发
中断源向中断控制器发送中断信号,中断控制器对中断进行仲裁,确定优先级,将中断信号发送给CPU
中断向量表
存储中断向量,中断向量与中断号对应,中断向量在中断向量表中接照中断号顺序存储
中断向量
中断服务程序的入口地址
中断管理使用说明
中断处理程序耗时不能过长,否则会影响CPU对中断的及时响应
中断响应过程中不能直接、间接执行引起调度的LOS_Schedule等函数
中断恢复LOsIntRestore()的入参必须是与之对应的LOSIntLock()的返回值(即关中断之前的CPSR值)
中断管理模块接口
软件定时器
描述
是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数。定时精度与系统Tick时钟的周期有关
硬件定时器受硬件的限制,数量上不足以满足用户的实际需求,因此为了满定用户需求,提供更多的定时器,LiteOS-M内核提供软件定时器功能
软件定时器扩展了定时器的数量,允许创建更多的定时业务
软件定时器是系统资源,在模块初始化的时候已经分配了一块连续卖的内存,系统支持的最大定时器个数由los_config.h中的LOSCFG BASE_CORE_SWTMR_LIMIT宏配置,
软件定时器特点
静态裁剪,能通过宏关闭软件定时器功能
软件定时器创建,软件定时器启动
软件定时器停止,软件定时器删除
软件定时器剩余Tick数获取
软件定时器运行机制
软件定时器使用了系统的一个队列和一个任务资源:其触发遵循队列规则,先进先出。定时时间短的定时器总是比定时时间长的靠近队列头,满足优先被触发的准则
软件定时器以Tick为基本计时单位:当用户创建并启动一个软件定时器时,LiteOS-M内核会根据当前系统Tick时间及用户设置的定时间隔确定该定时器的到期Tick时间,并将该定时器控制结构挂入计时全局链表
当Tick中断到来时:在Tick中断处理函数中扫描软件定时器的计时全局链表,看是否有定时器超时,若有则将超时的定时器记录下来
Tick中断处理函数结束后:软件定时器任务(优先级为最高)被唤醒,在该任务中调用之前记录下来的定时器的超时回调函数
软件定时器状态
OS_SWTMR_STATUS_UNUSED(未使用)
系统在定时器模块初始化的时候将系统中所有定时器资源初始化成该状态
OS_SWTMR_STATUS_CREATED(创建未启动/停止)
在未使用状态下调用LOS_SwtmrCreate接口或者启动后调用LOS_SwtmrStop接口后,定时器将变成该状态
OS_SWTMR STATUS_TICKING(计数)
在定时器创建后调用LOS_SwtmrStart接口,定时器将变成该状态,表示定时器运行时的状态
软件定时器模式
单次触发定时器
这类定时器在启动后只会触发一次定时器事件,然后定时器自动删除
周期触发定时器
这类定时器会周期性的触发定时器事件,直到用户手动地停止定时器,否则将永远持续执行下去
单次触发定时器(不会自动删除)
与第一类不同之处在于这类定时器超时后不会自动删除,需要调用定时器删除接口删除定时器
软件定时器使用说明
软件定时器的回调函数中不要做过多操作,不要使用可能引起任务挂起或者阻塞的接口或操作
软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级设定为0,且不充许修改
系统可配置的软件定时器资源个数是指:整个系统可使用的软件定时器资源总人数,而并非是用户可使用的软件定时器资源个数。例如:系统软件定时器多占用一个软件定时器资源数,那么用户能使用的软件定时器资源就会减少一个
创建单次不自删除属性的定时器,用户需要调用定时器删除接口删除定时器,回收定时器资源,避免资源泄露
创建单次软件定时器,该定时器超时执行完回调函后,系统会自动删除该软件定时器,并回收资源。
软件定时器开发流程
配置软件定时器
确认配置项LOSCFG_BASE_CORE_SWTMR和LOSCFG_BASE_IPC_QUEUE为1打开状态
配置LOSCFG_BASE_CORE_SWTMR_LIMIT最大支持的软件定时器数
配置OS_SWTMR_HANDLE_QUEUE_SIZE软件定时器队列最大长度
创建定时器LOS_SwtmrCreate
创建一人指定计时时长、指定超时处理函数、指定触发模式的软件定时器
返回函数运行结果,成功或失败
启动定时器LOS_SwtmrStart
获得软件定时器剩余Tick数LOS_SwtmrTimeGet
停止定时器LOs_SwtmrStop
删除定时器LOS SwtmrDelete
软件定时器模块接口
内存管理
描述
内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放
在系统运行过程中,内存管理模块通过对内存的电请/释放来管理用户和OS对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统的内存碎片问题
LiteOS-M的内存管理分为静态内存管理和动态内存管理,提供内存初始化、分配、释放等功能
静态内存管理
静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更
静态内存池由一个控制块LOS_MEMBOX_INFO和若干相同大小的内存块LOS_MEMBOX_NODE构成
初始化后的内存池的内存块数量,不等于总大小除于内存块大小,因为内存池的控制块和每个内存块的控制头,都存在内存开销,设置总大小时,需要将这些因素考虑进去
使用场景
当用户需要使用固定长度的内存时,可以通过静态内存分配的方式获取内存,一旦使用完毕,通过静态内存释放函数归还所占用内存,使之可以重复使用
控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext
静态内存开发流程
规划一片内存区域作为静态内存池
调用LOS_Memboxlnit初始化静态内存池。初始化会将入参指定的内存区域分割为N块(N值取决于静态内存总大小和块大小),将所有内存块挂到空闲链表,在内存起始处放置控制头
调用LOS_MemboxAlloc接口分配静态内存。系统将会从空闲链表中获取第一个空闲块,并返回该内存块的起始地址
调用LOS_MemboxClr接口。将入参地址对应的内存块清零
调用LOs MemboxFree接口。将该内存块加入空闲链表
分支主题
静态内存模块接口
动态内存管理
描述
动态内存管理:即在内存资源充足的情况下,根据用户需求,从系统配置的一块较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时又可以释放回系统供下一次使用。
LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能降低了碎片率。
使用场景
动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。动态内存 管理主要用于用户需要使用大小不等的内存块的场景,当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用
TLSF:Two-Level Segregated Fit 两级分割策略算法
动态内存与静态内存对比
动态内存
优点
按需分配
缺点
内存池中可能出现碎片
静态内存
优点
分配和释放效率高,静态内存池中无碎片
缺点
只能申请到初始化预设大小的内存块,不能按需申请
动态内存核心算法
OpenHarmony堆内存在TLSF(Two Level Segregated Fit memory allocator)算法的基础上,对区间划分做了优化,获得了更优的性能,减少了碎片率
根据空闲内存块的大小,使用多个空闲莲表来管理,根据内存空闲块大小分为两个部分:[4, 127]和[2^7, 2^31]
对「[4,127]区间的内存进行等分,如图下半部分所示,分为31个小区间,每个小区间 对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。[4,127]区间的31个小区间内对应31个比特位进行标记链表是否为空
大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每人小区间又等分为8个二级小区间,见图上半部分的Size Class和size Subclass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空
动态内存管理结构
OpenHarmonyLiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率
动态内存使用说明
由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存故实际用户可使用内存总量小于配置项OS_SYS_MEM_SIZE的大小
对齐分配内存接口LOs_MemAllocAlign/LOs_MemMallocAlign因为要进行地址对齐,可能会额外消耗部分内存,故存在一些遗失内存,当系统释放该对齐内存时,同时回收由于对齐导致的遗失内存
非连续性内存区域接口LOS_MemRegionsAdd的LosMemRegion数组参数传入的非连续性内存区域需要按各个内存区域的内存开始地址升序,且内存区域不能重叠
动态内存开发流程
1.初始化Los_Memlnit
初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。注:EndNode作为内存池未尾的节点,size为o。
2.申请任意大小的动态内存 Los_MemAlloc
判断动态内存池中是否存在大于申请量大小的空闲内存块空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。如果空闲内存块大于申请量,需要对内存块进行分割,剩余的部分作为空闲内存块挂载到空闲内存链表上。
3.释放动态内存 LOS_MemFree
可收内存块,供下一次使用。调用LOS_MemFree释放内存块,则会回收内存块,并且将其标记为FreeNode。在可收内存块时,相邻的FreeNode会自动合并。
动态内存接口
内核通信机制
事件
描述
事件是一种实现任务间通信的机制,可用于实现任务间的同步,但事件通信只能是事件,类型的通信,无数据传输。一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。事件集合用32位无符号整型变量来表示,每一位代表一个事件。
事件的第25位为保留位,不可以进行位设置
事件运作原理
事件(Event)是一种任务间的通信机制,可用于任务间的同步操作
事件处理模式
LOS_WAITMODE_AND
逻辑与,只有这些事件都已经发生才能读取成功,否则该任务将阻塞等待或者返回错误码
LOS_WAITMODE_OR
逻辑或,只要这些事件中有任一种事件发生就可以读取成功,否则该任务将阻塞等待或者返回错误码
LOS_WAITMODE_CLR
这是一种附加读取模式,需要与所有事件模式或任一事件模式结合使用( LOS_WAITMODE AND I LOS_ WAITMODE CLR或 LOS_WAITMODE_OR / LOS_WAITMODE CLR ) 在这种模式下,当设置的所有事件模式或任一事件模式读取成功后,会自动清除事件控制块中对应的事件类型位
事件开发使用说明与开发流程
任务间的事件同步,可以一对多,也可以多对多
一对多:表示一个任务可以等待多个事件
多对多:表示多个任务可以等待多个事件,一次写事件最多触发一个任务从阻塞中醒来
事件读超时机制
只做任务间同步,不传输具体数据
事件接口
互斥锁
描述
互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理
任意时刻互斥锁只有两种状态,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。当该任务释放它时,该互斤锁被开锁,任务失去该互斤锁的所有权。当一个任务持有互斤锁时,其他任务将不能再对该互片锁进行开锁或持有
多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。另外互斥锁可以解决信号量在的优先级翻转问题
互后锁使用说明
两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作
互斥锁不能在中断服务程序中使用
LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁
持有互斥锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥锁任务的优先级。
互斥锁开发流程
无阻塞模式
任务需要申请互斥锁,若该互压锁当前没有任务持有,或者持有该互斥锁的任务和申请该互斥锁的任务为同一人任务,则电请成功
永久阻塞模式
任务需要申请互斥锁,若该互斥锁当前没有被占申,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互任锁,阻塞任务才会重新得以执行
定时阻塞模式
任务需要申请互斥锁,若该互锁当前没有被占申,则请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,或者申户指定时间超时后,阻塞任务才会重新得以执行
互斥锁接口
消息队列
描述
队列文称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。
任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息
可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将者都队列和写队列的超时时但设置为大0的时间,就会以阳塞模式运行
消息队列特性
消息以先进先出的方式排队,支持异步读写
每读取一条消息,就会将该消息节点设置为空闲
发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息
一个任务能够从任意一个消息队列接收和发送消息
多个任务能够从同一个消息队列接收和发送消息
创建队列时所需的队列空间,接口内系统自行动态申请内存
读队列和写队列都支持超时机制
消息队列使用说明
系统支持的最大队列数:整个系统的队列资源总人数,而非用户能使用的个数。例如:系统软件定时器多占用一人队列资源,用户能使用的队列资源就会减少一个
创建队列时传入的队列名和flaqs暂时未使用,作为以后的预留参数
队列接口函数中的入参timeOut是相对时间
LOS_QueueReadCopy和LOS_QueueWriteCopy及LOS_QueueWriteHeadCopy是一组接口,LOS_QueueRead和LOS_QueueWrite及LOS_QueueWriteHead是一组接口,每组接口需要配套使用
timeOut是相对时间:消息队列与读写任务间的相对时间
鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口‧实 际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果
鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接‧口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败
LOS_QueueReadCopy接口的读取长度必须大于实际长度,否则消息将被截断
消息队列接口
信号量
描述
信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互访问。
一个信号量的数据结构中,通常有一个计数值, 用于对有效资源数的计数,表示剩下的可被使用 的共享资源数,其值的含义分两种情况:
0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务
正值,表示该信号量当前可被获取
以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同:
用作互斥时
用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制
用作同步时
用作同步时,初始信号量计数值为0。任务1因获取不到信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步
信号量开发流程
信号量初始化
为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG_BASE_IPC_SEM_LIMIT宏实现),并把所有信号量初始化成未使用,加入到未使用链表中供系统使用
创建信号量LOS_SemCreate
若要创建二值信号量则调用LOs_BinarySemCreate,从未使用的信号量链表中获取一个信号量,并设定初值
申请信号量LOS_SemPend
若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾
释放信号量LOS_SemPost
若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一人任务
删除信号量LOS_SemDelete
将正在使用的信号量置为未使用信号量,并挂回到未使用链表
信号量接口
内核扩展组件
CPU占用率
描述
CPU(中央处理器,Central ProcessingUnit)占用率分为系统CPU占用率和任务CPU占用率
系统CPU占用率(CPU Percent)
系统CPU占用率(CPUPerCent)是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示系统满负荷运转
任务CPU占用率
任务CPU占用率指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该任务
用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格
通过系统中各个任务的CPU占用情况,判断各个任务的CPU占用率是否符合设计的预期
CPU占用率运作机制
LiteOS-M的CPUP(CPUPercent,系统CPU占用率)采用任务级记录的方式,在任务切换时,记录任务启动时间,任务切出或者退出时间,每次当任务退出时,系统会累加整个任务的占用时间
LiteOS-M提供以下两种CPU占用率的信息查询
系统CPU占用率
任务CPU占用率
CPU占用率的计算方法
系统CPU占用率=系统中除idle任务外其他任务运行总时间/系统运行总时间
任务CPU占用率=任务运行总时间/系统运行总时间
CPU占用率运作可以在target_config.h的中对该功能进行选配
动态加载
描述
在硬件资源有限的小设备中,需器要通过法的动态部著能力来解决无法同时部暑多种算法的问题。以开发者易用为主要考虑因素,同时考虑到多平台的通用性,LiteOS-M选择业界标准的ELF加载方案,方便拓展算法生态
LiteOS-M提供类似于dlopen、dlsym等接口,APP通过动态加载模块提供的接口可以加载、卸载相应算法库
动态加载符号表导出
共享库调用内核接口需要内核主动暴露动态库所需的接口,该机制将符号信息编译到指定段中,调用SYM_EXPORT宏即可完成对指定符号的信息导出。
符号信息通过结构体Symlnfo描述,成员包括符号名和符号地址信息,宏SYM EXPORT通过_attribute_ 编译属性将符号信息导入.Sym.*段中。
动态加载ELF文件加载
加载过程中,根据ELF文件的句柄以及程序头表的段偏移可以得到需要加载到内存的LOAD段,一般有两个段,只读段及读写段,可以用readelf -L 查看ELF文件的LOAD段信息
根据相应的对齐属性申请物理内存,通过每个段的加载基址及偏移将代码段或数据段写入内存中
动态加载ELF文件链接
通过ELF文件的.dynamic段获取重定位表,遍历表中每一个需要重定位的条目,再根据需要重定位的符号名在共享库和内核提供的导出符号表中查找相应符号并更新相应的重定位信息。
ELE支持类型
编译共享库时,添加-fPIC可以编译出位置无关代码(-fPIC为编译选项),此时共享库文件类型为ET_DYN,其可以加载至任意有效的地址区间
例: arm-none-eabi-gcc -fPic -shared -o lib.so lib.c
LiteoS-A
M级内存设备
支持内存管理单元
适用于小型系统
主要应用于小型系统,面向设备一般是M级内存,可持MMU隔离,业界类似的内核有Zircon或Dawin等