《鸿蒙智能互联设备开发(微课版)》 课件汇 苗玉虎 第5-8章 LiteOS-A 内核 -智能出行设备开发_第1页
《鸿蒙智能互联设备开发(微课版)》 课件汇 苗玉虎 第5-8章 LiteOS-A 内核 -智能出行设备开发_第2页
《鸿蒙智能互联设备开发(微课版)》 课件汇 苗玉虎 第5-8章 LiteOS-A 内核 -智能出行设备开发_第3页
《鸿蒙智能互联设备开发(微课版)》 课件汇 苗玉虎 第5-8章 LiteOS-A 内核 -智能出行设备开发_第4页
《鸿蒙智能互联设备开发(微课版)》 课件汇 苗玉虎 第5-8章 LiteOS-A 内核 -智能出行设备开发_第5页
已阅读5页,还剩284页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

5.1.1LiteOS-A内核简介通过本节学习,您可以:了解LiteOS-A内核简介LiteOS-A内核简介LiteOS-A适配的系统及设备类型:小型系统(smallsystem)面向应用处理器例如ArmCortex-A的设备,支持的设备最小内存为1MB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IPCamera、电子猫眼、路由器以及智慧出行域的行车记录仪等。LiteOS-A要求设备具备一定的处理能力,对比LiteOS-M,LiteOS-A支持以下特性:(1)MMU支持:通过MMU支持内核态和用户态分离,支持虚拟单元;(2)支持独立进程:调度对象分别为进程、线程;(3)支持文件系统:包括虚拟文件和块设备等;(4)支持更复杂的IPC:包括LiteIPC等;(5)支持多核调度:支持双核MCU,支持双核调度;(6)支持POSIX3接口:为APP开发提供更多帮助。LiteOS-A内核简介LiteOS-A的源码目录:关键目录:arch:存放了arm架构相关的代码,以及中断管理相关代码compat:POSIX标准目的是为了提供源码级的软件可移植性。一个系统提供了POSIX接口,则任何其它的系统可以通过POSIX调用该系统drivers:内核驱动代码,分别对应块设备驱动、字符设备驱动、内存设备驱动LiteOS-A内核简介关键目录:kernel:base:基础内核,进程管理、内存管理、内核通信机制、时间管理、软件定时器等模块。include:内核相关模块头文件。LiteOS-A的源码目录:谢谢5.1.2LiteOS-A内核架构通过本节学习,您可以:了解LiteOS-A内核架构LiteOS-A内核架构LiteOS-A内核分为内核空间和用户空间,如图所示。LiteOS-A内核架构(1)基础内核:进程管理:支持进程和线程,采用了高优先级优先加同优先级时间片轮转的抢占式调度机制。内存管理:对物理内存和虚拟内存分别进行管理。中断异常:对中断的异常处理。时间管理:对操作系统时间进行管理,提供给应用程序所有和时间有关的服务。通信机制:包括事件、信号量、互斥锁、消息队列、信号等。1.

内核空间LiteOS-A内核架构(2)扩展组件:主要包括文件系统、网络协议、权限管理、动态加载、调测工具等。文件系统:轻量级内核支持FAT,JFFS2,NFS,ramfs,procfs等众多文件系统,并对外提供完整的POSIX标准的操作接口;内部使用VFS(VirtualFileSystems,虚拟文件系统)层作为统一的适配层框架,方便移植新的文件系统,各个文件系统也能自动利用VFS层提供的丰富的功能。LiteOS-A内核架构网络协议:网络协议基于开源LWIP(LightWeightIP协议)构建。支持多种协议:IP、ICMP、ND、MLD、UDP、TCP、IGMP、ARP、PPP支持的API:socketAPI网络协议的扩展特性:多网络接口IP转发、TCP拥塞控制、RTT估计和快速恢复、快速重传。支持多种应用程序LiteOS-A内核架构支持的协议:IP协议:包括IPV4和IPV6,支持IP分片于重装,支持多网络接口下数据包转发。ICMP协议:用于网络调试维护。ND(NeighborDiscovery)协议:IP6邻居发现协议。MLD协议:组播侦听发现协议,于IPv6组播中组成员管理。UDP协议:用户数据包协议。TCP:支持TCP拥塞控制,RTT估计,快恢复和重传等。IGMP:用于网络组管理,可以实现多播数据的接收。ARP协议:地址解析协议。PPP协议:包括PPPoS(串口点对点协议)、PPPoE(以太网上的点对点协议)。LiteOS-A内核架构适用的应用程序:HTTP(S)服务SNTP客户端SMTP(S)客户端ping工具NetBIOS名称服务mDNS响应程序MQTT客户端TFTP服务DHCP客户端DNS客户端AutoIP/APIPA(零配置)SNMP代理LiteOS-A内核架构(3)HDF框架HDF框架是外设驱动统一标准框架,提供了GPIO、SDIO、I2C、USB、WLAN等各种外设接口方式。HDF框架特性:支持多内核平台。支持用户态驱动。可配置组件化驱动模型。基于消息的驱动接口模型。基于对象的驱动、设备管理。HDI(HardwareDriverInterface)统一硬件接口。支持电源管理、PnP(Plug-and-Play,即插即用)。LiteOS-A内核架构LiteOS-A内核架构的顶部是用户空间,用户空间主要是用户进程和POSIX接口组成。OpenHarmony内核使用musllibc库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。2.用户空间谢谢5.1.3LiteOS-A内核态启动流程通过本节学习,您可以:了解LiteOS-A内核态启动流程LiteOS-A内核态启动流程内核启动流程如图所示。LiteOS-A内核态启动流程内核启动流程包含汇编启动阶段和C语言启动阶段两部分。汇编启动阶段完成CPU初始设置,关闭dcache/icache与MMU,使能FPU及neon,设置MMU建立虚实地址映射,设置系统栈,清理bss段,调用C语言main函数等。C语言启动阶段包含OsMain函数及开始调度等。LiteOS-A内核态启动流程OsMain函数用于内核基础初始化和架构、板级初始化等,其整体由内核启动框架主导初始化流程,如图所示。LiteOS-A内核态启动流程①LOS_INIT_LEVEL_EARLIEST:最早期初始化。不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始,例如:内核Trace模块初始化。②LOS_INIT_LEVEL_ARCH_EARLY:架构早期初始化。与架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到⑥LOS_INIT_LEVEL_ARCH层。LiteOS-A内核态启动流程③LOS_INIT_LEVEL_PLATFORM_EARLY:平台早期初始化。与单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到⑦LOS_INIT_LEVEL_PLATFORM层。④LOS_INIT_LEVEL_KMOD_PREVM:内存初始化前的内核模块初始化。在内存初始化之前需要使能的模块初始化。LiteOS-A内核态启动流程⑤LOS_INIT_LEVEL_VM_COMPLETE:基础内存就绪后的初始化。此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化。⑥LOS_INIT_LEVEL_ARCH:架构后期初始化。与架构拓展功能相关,后续模块会对其有依赖的模块初始化。LiteOS-A内核态启动流程⑦LOS_INIT_LEVEL_PLATFORM:平台后期初始化。单板平台、驱动相关,后续模块会对其有依赖的模块初始化,例如:驱动内核抽象层初始化(mmc、mtd)。⑧LOS_INIT_LEVEL_KMOD_BASIC:内核基础模块初始化。内核可拆卸的基础模块初始化。例如:VFS初始化。LiteOS-A内核态启动流程⑨LOS_INIT_LEVEL_KMOD_EXTENDED:内核扩展模块初始化。内核可拆卸的扩展模块初始化。例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、LiteIPC初始化。⑩LOS_INIT_LEVEL_KMOD_TASK:内核任务创建。进行内核任务的创建(内核任务,软件定时器任务)。例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建等。谢谢5.1.4LiteOS-A用户态启动流程通过本节学习,您可以:了解LiteOS-A用户态启动流程LiteOS-A用户态启动流程用户态启动是从根进程开始的。根进程是系统的第一个用户态进程,进程ID为1。用户态启动进程树如图所示。1号进程接下来会创建和启动其他的用户态进程例如/bin/shell。LiteOS-A用户态启动流程鸿蒙中的init进程作用类似于Linux中的init进程,主要作用是完成系统启动后,用户可以操作前的一些初始化操作,例如孵化一些用户的服务,创建一些必要的文件目录结构等。Init进程是由SysemInit()函数来启动的,SystemInit()函数代码如下所示:

SystemInit()

ProcFsInit();

mem_dev_register();

imx6ull_driver_init();

imx6ull_mount_rootfs();

DeviceManagerStart();//HDF,加载驱动,使外设可以正常工作。

uart_dev_init();

......

OsUserInitProcess();LiteOS-A用户态启动流程在SystemInit()函数中,通过OsUserInitProcess()启动init进程,具体是通过OsUserInitProcessStart()函数来实现的。OsUserInitProcessStart()函数的代码如下:

STATICUINT32OsUserInitProcessStart(UINT32processID,TSK_INIT_PARAM_S*param)

{

UINT32intSave;

INT32taskID;

INT32ret;

taskID=OsCreateUserTask(processID,param);

if(taskID<0){

returnLOS_NOK;

}

ret=LOS_SetTaskScheduler(taskID,LOS_SCHED_RR,OS_TASK_PRIORITY_LOWEST);

if(ret<0){

PRINT_ERR("Userinitprocesssetschedulerfailed!ERROR:%d\n",ret);

SCHEDULER_LOCK(intSave);

(VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(taskID),OS_PRO_EXIT_OK,intSave);

return-ret;

}

returnLOS_OK;

}谢谢5.2.1中断与异常处理的概念和机制通过本节学习,您可以:了解中断与异常处理的概念和机制中断与异常处理的概念中断异常处理是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,例如虚拟内存缺页异常、打印异常发生时函数的调用栈信息、CPU现场信息、任务的堆栈情况等。异常指可以打断CPU正常运行流程的一些事情,如未定义指令异常、试图修改只读的数据异常、不对齐的地址访问异常等。中断与异常处理机制LiteOS-A的中断异常处理流程:外设可以在没有CPU介入的情况下完成一定的工作,但某些情况下也需要CPU为其执行一定的工作。当外设需要CPU时,将产生一个中断信号,该信号连接至中断控制器。中断控制器是一方面接收其它外设中断引脚的输入,另一方面它会发出中断信号给CPU。可以通过对中断控制器编程来打开和关闭中断源、设置中断源的优先级和触发方式。CPU收到中断控制器发送的中断信号后,中断当前任务来响应中断请求。当异常发生时,CPU暂停当前的程序,先处理异常事件,然后再继续执行被异常打断的程序。中断与异常处理机制常用的中断控制器有VIC(VectorInterruptController,向量中断控制器)和GIC(GeneralInterruptController,通用中断控制器)。LiteOS-A内核支持的是ARM公司的Cortex-A/R系列的芯片,GIC是ARM公司给Cortex-A/R系列芯片提供的一个中断控制器,类似Cortex-M中的NVIC。GIC控制器有4个版本V1-V4,V2版本是给ARMv7-A架构使用的,比如Cortex-A5,Cortex-A7、Cortex-A9、Cortex-A15等。中断与异常处理机制当GIC控制器接收到外部中断信号以后汇报给ARM内核,ARM内核提供了四个信号给GIC来汇报中断情况:VFIQ、VIRQ、FIQ和IRQ,如图所示。中断与异常处理机制4个信号含义如下:VFIQ:虚拟快速FIQVIRQ:虚拟外部IRQFIQ:快速中断IRQIRQ:外部中断IRQGIC控制器接收众多的外部中断,并对其进行处理,最终通过四个信号报给ARM内核。中断与异常处理的概念和机制LiteOS-A当前支持ARMv7-a指令集架构,以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的中断向量,如表所示。中断向量异常中断名称_exception_handlersresetvector复位osExceptUndeflnstrHd未定义的指令osExceptSwiHdl软件中断osExceptPrefetchAbortHdl预取指令中止osExceptDataAbortHdl数据访问中止osExceptAddrAbortHd地址异常中止OslrqHandler外部中断请求osExceptFiqHd快速中断请求谢谢5.2.2中断与异常处理接口与应用通过本节学习,您可以:了解中断与异常处理接口说明与应用中断与异常处理接口与应用OpenHarmonyLiteOS-A内核的中断模块提供的接口跟LiteOS-M基本相同,包括创建中断、删除中断、打开和关闭中断等接口,如表所示。1.

中断与异常处理管理接口功能分类接口名描述创建中断LOS_HwiCreate中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序删除中断LOS_HwiDelete根据指定的中断号,删除中断打开中断LOS_IntUnLock打开当前处理器所有中断响应关闭中断LOS_IntLock关闭当前处理器所有中断响应恢复中断LOS_IntRestore与LOS_IntLock配套使用,恢复到使用LOS_IntLock关闭所有中断之前的状态中断与异常处理接口与应用中断管理的一般开发流程如下:(1)调用中断创建接口LOS_HwiCreate创建中断。(2)调用LOS_HwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。2.中断管理应用谢谢5.3.1进程管理通过本节学习,您可以:了解进程管理进程管理进程是系统资源管理的基本单元。OpenHarmonyLiteOS-A内核提供的进程模块主要用于实现用户态进程的隔离,不涉及内核态进程。进程模块主要为用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。进程采用抢占式调度机制,采用高优先级优先加同优先级时间片轮转的调度算法。进程一共有32个优先级(0-31),用户进程可配置的优先级有22个(10-31),最高优先级为10,最低优先级为31。高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。用户态根进程init由内核态创建,其它用户态子进程均由init进程创建而来。1.

进程的概念进程管理进程有多种状态,各状态之间的关系如图所示:2.进程状态初始化(Init):进程正在被创建。就绪态(Ready):进程在就绪列表中,等待CPU调度。运行态(Running):进程正在运行。阻塞态(Pending):进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。僵尸态(Zombies):进程运行结束,等待父进程回收其控制块资源。进程管理初始化→就绪态:进程创建或fork时,拿到对应进程控制块后进入Init状态,即进程初始化阶段,当该阶段完成后进程将被插入调度队列,此时进程进入就绪状态。就绪态→运行态:发生进程切换时,就绪列表中优先级最高且获得时间片的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存,但对外呈现的进程状态为运行态。

初始化就绪态阻塞态运行态僵尸态进程管理运行态→阻塞态:进程在最后一个线程转为阻塞态时,进程内所有的线程均处于阻塞态,此时进程同步进入阻塞态,然后发生进程切换。阻塞态→就绪态:阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。就绪态→阻塞态:进程内的最后一个就绪态线程转为阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。

初始化就绪态阻塞态运行态僵尸态进程管理运行态→就绪态:有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。若进程的调度策略为LOS_SCHED_RR(时间片轮转),且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。

初始化就绪态阻塞态运行态僵尸态进程管理运行态→僵尸态:当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。

初始化就绪态阻塞态运行态僵尸态进程管理进程管理主要是合理的分配各个进程使用CPU的时间。用户态进程由Init进程分解而来,如图所示。fork进程时会将父进程的进程虚拟内存空间克隆到子进程,子进程实际运行时通过写时复制机制将父进程的内容按需复制到子进程的虚拟内存空间。3.进程运行机制用户态进程

多线程用户态进程

多线程Init进程

多线程进程管理OpenHarmonyLiteOS-A内核的进程管理模块提供了进程组、用户组、进程创建等接口。4.进程接口功能分类接口名接口描述获取进程IDLOS_GetCurrProcessID获取当前进程的进程ID进程组LOS_GetProcessGroupID获取指定进程的进程组IDLOS_GetCurrProcessGroupID获取当前进程的进程组ID用户及用户组LOS_GetUserID获取当前进程的用户IDLOS_GetGroupID获取当前进程的用户组IDLOS_CheckInGroups检查指定用户组ID是否在当前进程的用户组内进程管理功能分类接口名接口描述进度调度参数控制LOS_GetProcessScheduler获取指定进程的调度策略LOS_SetProcessScheduler设置指定进程的调度参数,包括优先级和调度策略LOS_SetProcessPriority设置进程优先级LOS_GetProcessPriority获取进程优先级系统支持的最大进程数LOS_GetSystemProcessMaximum获取系统支持的最大进程数目LOS_GetUsedPIDList获得已使用的进程ID列表进程管理功能分类接口名接口描述创建进程LOS_Fork创建子进程等待进程LOS_Wait等待子进程结束并回收子进程LOS_Waitid等待相应ID的进程结束退出进程LOS_Exit退出进程谢谢5.3.2任务管理通过本节学习,您可以:了解任务管理任务管理从系统的角度看,任务Task是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。OpenHarmony内核中使用一个任务表示一个线程。OpenHarmony内核中同优先级进程内的任务统一调度、运行。OpenHarmony内核中的任务采用抢占式调度机制,同时支持时间片轮转调度和FIFO调度方式。内核的任务一共有32个优先级(0-31),最高优先级为0,最低优先级为31。当前进程内,高优先级的任务可抢占低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。1.

任务管理概念任务管理任务的各状态如图所示:

初始化就绪态阻塞态运行态退出初始化(Init):任务正在被创建。就绪态(Ready):任务在就绪队列中,等待CPU调度。运行态(Running):任务正在运行。阻塞态(Blocked):任务被阻塞挂起。Blocked状态包括:pending(因为锁、事件、信号量等阻塞)、suspended(主动pend)、delay(延时阻塞)、pendtime(因为锁、事件、信号量时间等超时等待)。退出态(Exit):任务运行结束,等待父任务回收其控制块资源。任务管理初始化→就绪态:任务创建拿到控制块后为初始化阶段(Init状态),当任务初始化完成将任务插入调度队列,此时任务进入就绪状态。就绪态→运行态:任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,此刻该任务从就绪队列中删除。

初始化就绪态阻塞态运行态退出任务管理运行态→阻塞态:正在运行的任务发生阻塞(挂起、延时、读信号量等)时,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中剩余最高优先级任务。阻塞态→就绪态:阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态。

初始化就绪态阻塞态运行态退出任务管理就绪态→阻塞态:任务也有可能在就绪态时被阻塞(挂起),此时任务状态会由就绪态转变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复。运行态→就绪态:有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,并加入就绪队列中。

初始化就绪态阻塞态运行态退出任务管理运行态→退出态:运行中的任务运行结束,任务状态由运行态变为退出态。

初始化就绪态阻塞态运行态退出任务管理OpenHarmonyLiteOS-A内核的任务管理模块提供了创建任务、删除任务、控制任务状态、获取任务信息等几种功能,具体如表所示。2.任务管理接口功能分类接口名接口描述任务的创建和删除

LOS_TaskCreate创建任务,若所创建任务的优先级比当前的运行的任务优先级高且任务调度没有锁定,则该任务将被调度进入运行态LOS_TaskCreateOnly创建任务并阻塞,任务恢复前不会将其加入就绪队列中LOS_TaskDelete删除指定的任务,回收其任务控制块和任务栈所消耗的资源任务的状态控制

LOS_TaskResume恢复挂起的任务LOS_TaskSuspend挂起指定的任务,该任务将从就绪任务队列中移除LOS_TaskJoin阻塞当前任务,等待指定任务运行结束并回收其资源LOS_TaskDetach修改任务的joinable属性为detach属性,detach属性的任务运行结束会自动回收任务控制块资源LOS_TaskDelay延迟当前任务的执行,在延后指定的时间(tick数)后可以被调度LOS_TaskYield将当前任务从具有相同优先级的任务队列,移动到就绪任务队列的末尾任务管理功能分类接口名接口描述任务调度

LOS_TaskLock锁定任务调度,阻止任务切换LOS_TaskUnlock解锁任务调度。通过该接口可以使任务锁数量减1,若任务多次加锁,那么任务调度在锁数量减为0时才会完全解锁LOS_GetTaskScheduler获取指定任务的调度策略LOS_SetTaskScheduler设置指定任务的调度参数,包括优先级和调度策略LOS_Schedule触发主动的任务调度任务信息获取

LOS_CurTaskIDGet获取当前任务的IDLOS_TaskInfoGet获取指定任务的信息LOS_GetSystemTaskMaximum获取系统支持的最大任务数任务优先级

LOS_CurTaskPriSet设置当前正在运行的任务的优先级LOS_TaskPriSet设置指定任务的优先级LOS_TaskPriGet获取指定任务的优先级任务绑核操作

LOS_TaskCpuAffiSet绑定指定任务到指定CPU上运行,仅在多核下使用LOS_TaskCpuAffiGet获取指定任务的绑核信息,仅在多核下使用任务管理任务管理的一般开发流程如下:(1)通过LOS_TaskCreate创建一个任务。指定任务的执行入口函数指定任务名指定任务的栈大小指定任务的优先级(2)任务参与调度运行,执行用户指定的业务代码。(3)任务执行结束。3.任务管理应用谢谢5.3.3调度器通过本节学习,您可以:了解调度器调度器调度器(scheduler)是一个操作系统的核心部分,是CPU时间的管理员,负责选择最适合的就绪进程来执行。1.

调度器概念周期性调度器CPU上下文切换主调度器选择进程调度器类进程调度器主要完成两件事:选择某些就绪进程来执行。打断某些执行的进程让他们变为就绪态调度器主调度器:通过调用schedule()函数来完成进程的选择和切换。周期性调度器:根据频率自动调用scheduler_tick函数,根据进程运行时间触发调度。上下文切换:主要做两个事情,切换地址空间、切换寄存器和栈空间。调度器类:每个调度器都有一个优先级,它会按照优先级顺序遍历调度类,拥有一个可执行进程的最高优先级的调度器类胜出,去选择下面要执行的那一个程序。周期性调度器CPU上下文切换主调度器选择进程调度器类进程调度器2.调度器运行机制OpenHarmony在系统启动内核初始化之后开始调度。系统根据进程和线程的优先级及线程的时间片消耗情况选择最优的线程进行调度运行。线程一旦调度到就会从调度队列上删除,线程在运行过程中发生阻塞,会被加入到对应的阻塞队列中并触发一次调度,调度其它线程运行。如果调度队列上没有可以调度的线程,则系统就会选择KIdle进程的线程进行调度运行。调度器OpenHarmonyLiteOS-A内核的调度器模块提供了调度相关的接口。3.调度器接口功能分类接口名称描述触发系统调度LOS_Schedule触发系统调度LOS_GetTaskScheduler获取指定任务的调度策略LOS_SetTaskScheduler设置指定任务的调度策略LOS_GetProcessScheduler获取指定进程的调度策略LOS_SetProcessScheduler设置指定进程的调度参数,包括优先级和调度策略调度器进程管理的应用,具体代码如下:

#include<stdio.h>

#include"osal_thread.h"

/**

*@brief输出“helloohos”函数

*@paramvoid

*@retvalvoid

*/

voidTask_hello_ohos(void)

{

while(1)

{

printf("Helloohos!!!\r\n");

}

}

/**

*@brief任务创建函数

*@paramvoid

*@retvalvoid

*/

调度器

intmain(intargc,char**argv)

{

structOsalThreadtask_ohos;//ohos任务ID

structOsalThreadParamtaskoh;//定义ohos任务结构体

taskoh.stackSize=1028;//任务堆栈

="Task_hello_ohos";//任务名称

taskoh.priority=OSAL_THREAD_PRI_LOW;//任务优先级

/**创建任务**/

if(OsalThreadCreate(&task_ohos,Task_hello_ohos,NULL)!=HDF_SUCCESS)

{

printf("task_ohoscreateFailed!\r\n");

}

printf("task_ohoscreatesuccessful!\r\n");

if(OsalThreadStart(&task_ohos,&taskoh)!=HDF_SUCCESS)

{

printf("task_ohosstartFailed!\r\n");

}

printf("task_ohosstartsuccessful!\r\n");}调度器运行结果如下:谢谢6.1.1

HDF驱动框架介绍通过本节学习,您可以:了解HDF驱动框架HDF驱动框架介绍HDF驱动框架介绍:HDF驱动架构采用C语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动一次开发,多系统部署的效果。HDF驱动框架介绍HDF驱动框架架构组成:OSAL:操作系统抽象层(OperatingSystemAbstractionLayer),提供统一封装的内核操作相关接口,屏蔽不同系统操作差异,包含内存、锁、线程、信号量等接口。HDF驱动框架介绍HDF驱动框架架构组成:1.HDF驱动基础框架:提供统一的硬件资源管理,驱动加载管理以及设备节点管理等功能。驱动框架采用的是主从模式设计,由DeviceManager和DeviceHost组成。HDF驱动框架介绍HDF驱动框架架构组成:2.驱动程序:实现驱动具体的功能,每个驱动由一个或者多个驱动程序组成,每个驱动程序都对应着一个DriverEntry。HDF驱动框架介绍HDF驱动框架架构组成:3.驱动配置文件.hcs:主要由设备信息(DeviceInformation)和设备资源(DeviceResource)组成。HDF驱动框架介绍HDF驱动框架架构组成:4.驱动接口:HDI(HardwareDriverinterface,硬件设备接口)提供标准化的接口定义和实现,驱动框架提供IOService和IODispatcher机制,使得不同部署形态下驱动接口趋于形式一致。谢谢6.1.2HDF驱动模型介绍通过本节学习,您可以:了解HDF驱动模型HDF驱动模型介绍HDF设备驱动模型的组成:Host(设备容器)、Device(设备)、DeviceNode(设备节点)、Driver(驱动程序)。HDF框架将一类设备驱动放在同一个Host里面,用于管理一组设备的启动加载等过程。Device对应一个真实的物理设备。DeviceNode是设备的一个部件,Device至少有一个DeviceNode。每个DeviceNode可以发布一个设备服务。每个DevicdNode唯一对应一个驱动,实现和硬件的功能交互。HDF驱动模型介绍在划分Host时,驱动程序是部署在一个Host还是部署在不同的Host,主要考虑驱动程序之间是否存在耦合性,如果两个驱动程序之间存在依赖,可以考虑将这部分驱动程序部署在一个Host里面。Host有两种属性:hostName,priority属性取值描述hostName字符串设备集合的名称。Priority整数,0-200设备集合的优先级。数值越大,优先级越低;如果优先级相同,则不能保证加载顺序。HDF驱动模型介绍HDF驱动框架给DeviceNode设备节点定义的属性:属性取值描述moduleName字符串每个设备节点所对应的驱动程序被称为一个module,每一个module都有一个moduleName。preload整数驱动被HDF加载的方式Priority整数,0-200驱动的优先级。数值越大,优先级越低;如果优先级相同,则不能保证加载顺序。serviceNamen字符串驱动对外发布的服务的名称,必须唯一。policy整数驱动对外发布服务的策略。permission整数设备节点的读写权限,一般采用以0为前缀的8进制整数,类似于linux的文件权限的概念。deviceMatchAttr字符串用于匹配设备节点的自定义属性。HDF驱动模型介绍驱动的加载方式如下:

typedef

enum{

DEVICE_PRELOAD_ENABLE=0,

DEVICE_PRELOAD_ENABLE_STEP2,

DEVICE_PRELOAD_DISABLE,

DEVICE_PRELOAD_INVALID

}DevicePreload;preload字段配置为0(DEVICE_PRELOAD_ENABLE),则系统启动过程中默认加载。preload字段配置为1(DEVICE_PRELOAD_ENABLE_STEP2),当系统支持快速启动的时候,则在系统完成之后再加载这一类驱动。preload字段配置为2(DEVICE_PRELOAD_DISABLE),则系统启动过程中默认不加载。谢谢6.1.3HDF驱动开发步骤通过本节学习,您可以:了解HDF驱动开发步骤HDF驱动开发步骤HDF框架的驱动开发的组成部分:驱动实现、驱动编译脚本编写和驱动配置。1.驱动实现:驱动实现包含驱动业务代码实现和驱动入口注册,具体写法如下:(1)驱动业务代码模板

#include"hdf_device_desc.h"//HDF框架对驱动开发相关能力接口的头文件

#include"hdf_log.h"//HDF框架提供的日志接口头文件

#defineHDF_LOG_TAGtest_driver//打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签。

//将驱动对外提供的服务能力接口绑定到HDF框架。

int32_tHdfTestDriverBind(structHdfDeviceObject*deviceObject){

HDF_LOGD("Testdriverbindsuccess");

returnHDF_SUCCESS;

}

//驱动自身业务初始化的接口

int32_tHdfTestDriverInit(structHdfDeviceObject*deviceObject){

HDF_LOGD("TestdriverInitsuccess");

returnHDF_SUCCESS;

}

//驱动资源释放的接口

voidHdfTestDriverRelease(structHdfDeviceObject*deviceObject){

HDF_LOGD("Testdriverreleasesuccess");

return;

}HDF驱动开发步骤(2)驱动入口注册到HDF框架

structHdfDriverEntryg_testDriverEntry={

.moduleVersion=1,

.moduleName="test_driver",

.Bind=HdfTestDriverBind,

.Init=HdfTestDriverInit,

.Release=HdfTestDriverRelease,

};

//调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。

HDF_INIT(g_testDriverEntry);驱动注册,就是实例化驱动入口,驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。HDF驱动开发步骤2.驱动编译脚本编写添加模块BUILD.gn把新增模块的BUILD.gn所在的目录添加到上一级BUILD.gn文件中

import("//drivers/adapter/khdf/liteos/hdf.gni")

hdf_driver("hdf_led"){

sources=[

"led.c",#此处为点灯实验,根据实验进行修改

]

include_dirs=[

"//device/st/drivers/module_driver/Module_Common/inc/",

]}

group("drivers"){

deps=[

"led",#新增模块BUILD.gn的名称,根据实验进行修改

]

}HDF驱动开发步骤3.驱动配置驱动配置包含两部分:HDF框架定义的驱动设备描述和驱动的私有配置信息。(1)驱动设备描述HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描述。

root{

device_info{

match_attr="hdf_manager";HDF驱动开发步骤

templatehost{//host模板,继承该模板的节点(如下test_host)如果使用模板中的默认值,则节点字段可以缺省。

hostName="";

priority=100;

templatedevice{

templatedeviceNode{

policy=0;

priority=100;

preload=0;

permission=0664;

moduleName="";

serviceName="";

deviceMatchAttr="";

}

}

}HDF驱动开发步骤

platform::host{

hostName="platform_host";//host名称,host节点是用来存放某一类驱动的容器。

priority=50;//host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序。

device_led::device{//led设备节点

device0::deviceNode{//led驱动的DeviceNode节点

policy=2;//policy字段是驱动服务发布的策略

priority=200;//驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序

preload=0;//驱动按需加载字段

permission=0777;//驱动创建设备节点权限

moduleName="HDF_LED";//驱动名称,该字段的值必须和驱动入口结构的moduleName值一致

serviceName="hdf_led";//驱动对外发布服务的名称,必须唯一

deviceMatchAttr="st_stm32mp157_led";//驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等

}

}

}

}}HDF驱动开发步骤(2)驱动私有配置信息如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息。HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject中的property里面,通过Bind和Init传递给驱动。驱动的配置信息示例如下:配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs,示例如下:

root{

LedDriverConfig{

led_gpio_num=13;

match_attr="st_stm32mp157_led";//该字段的值必须和device_info.hcs中的deviceMatchAttr值一致

}

}

#include"device_info/device_info.hcs"

#include"led/led_config.hcs"

谢谢6.2.1驱动服务介绍通过本节学习,您可以:了解驱动服务介绍驱动服务介绍当驱动需要以接口的形式对外提供能力时,可以使用HDF框架的驱动服务管理能力。驱动服务是HDF驱动设备对外提供能力的对象,由HDF框架统一管理。驱动服务管理主要包含驱动服务的发布和获取。1.驱动服务的发布:HDF框架定义了驱动对外发布服务的策略,由配置文件中的policy字段来控制,policy字段的取值范围以及含义如下:

typedef

enum{

SERVICE_POLICY_NONE=0,//驱动不提供服务

SERVICE_POLICY_PUBLIC=1,//驱动对内核态发布服务

SERVICE_POLICY_CAPACITY=2,//驱动对内核态和用户态都发布服务

SERVICE_POLICY_FRIENDLY=3,//驱动服务不对外发布服务,但可以被订阅

SERVICE_POLICY_PRIVATE=4,//驱动私有服务不对外发布服务,也不能被订阅

SERVICE_POLICY_INVALID//错误的服务策略

}ServicePolicy;驱动服务介绍2.驱动服务的获取:驱动服务的获取有两种方式:通过HDF接口直接获取:当明确驱动已经加载完成时,获取该驱动的服务可以通过HDF框架提供的能力接口直接获取。通过HDF提供的订阅机制获取:当内核态对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的阅机

制来订阅该驱动,当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者。谢谢6.2.2驱动服务管理开发通过本节学习,您可以:了解驱动服务管理开发驱动服务管理开发1.驱动服务管理接口针对驱动服务管理功能,HDF框架开放了部分接口给开发者调用。方法描述int32_t(*Bind)(structHdfDeviceObject*deviceObject);需要驱动开发者实现Bind函数,将自己的服务接口绑定到HDF框架中conststructHdfObject*DevSvcManagerClntGetService(constchar*svcName);获取驱动的服务intHdfDeviceSubscribeService(structHdfDeviceObject*deviceObject,constchar*serviceName,structSubscriberCallbackcallback);订阅驱动的服务驱动服务管理开发2.驱动服务管理开发步骤(1)驱动服务的编写驱动服务管理开发的第一步是定义驱动的服务接口。

//驱动服务结构的定义

structITestDriverService{

structIDeviceIoServiceioService;//服务结构的首个成员必须是IDeviceIoService类型的成员

int32_t(*ServiceA)(void);//驱动的第一个服务接口

int32_t(*ServiceB)(uint32_tinputCode);//驱动的第二个服务接口,有多个可以依次往下累加

};

驱动服务接口的实现

int32_tTestDriverServiceA(void)

{

//驱动开发者实现业务逻辑

returnHDF_SUCCESS;

}

int32_tTestDriverServiceB(uint32_tinputCode)

{

//驱动开发者实现业务逻辑

returnHDF_SUCCESS;

}驱动服务管理开发(2)驱动服务绑定驱动服务绑定到HDF框架中,实现HdfDriverEntry中的Bind指针函数。

int32_tTestDriverBind(structHdfDeviceObject*deviceObject)

{

//deviceObject为HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口

if(deviceObject==NULL){

HDF_LOGE("Testdeviceobjectisnull!");

returnHDF_FAILURE;

}

static

structITestDriverServicetestDriverA={

.ServiceA=TestDriverServiceA,

.ServiceB=TestDriverServiceB,

};

deviceObject->service=&testDriverA.ioService;

returnHDF_SUCCESS;

}驱动服务管理开发(3)驱动服务获取通过HDF接口直接获取:

const

structITestDriverService*testService=

(const

structITestDriverService*)DevSvcManagerClntGetService("test_driver");

if(testService==NULL){

returnHDF_FAILURE;

}

testService->ServiceA();testService->ServiceB(5);驱动服务管理开发

//object为订阅者的私有数据,service为被订阅的服务对象

int32_tTestDriverSubCallBack(structHdfDeviceObject*deviceObject,const

structHdfObject*service)

{

const

structITestDriverService*testService=

(const

structITestDriverService*)service;

if(testService==NULL){

returnHDF_FAILURE;

}

testService->ServiceA();

testService->ServiceB(5);

}通过HDF提供的订阅机制获取:需要编写订阅回调函数,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用。驱动服务管理开发

//订阅过程的实现

int32_tTestDriverInit(structHdfDeviceObject*deviceObject)

{

if(deviceObject==NULL){

HDF_LOGE("Testdriverinitfailed,deviceObjectisnull!");

returnHDF_FAILURE;

}

structSubscriberCallbackcallBack;

callBack.deviceObject=deviceObject;

callBack.OnServiceConnected=TestDriverSubCallBack;

int32_tret=HdfDeviceSubscribeService(deviceObject,"test_driver",callBack);

if(ret!=HDF_SUCCESS){

HDF_LOGE("Testdriversubscribetestdriverfailed!");

}

returnret;}谢谢6.3.1驱动消息机制管理通过本节学习,您可以:了解驱动消息机制管理驱动消息机制管理鸿蒙系统的的HDF框架提供了统一的驱动消息机制。当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。用户态:指应用程序运行的环境,应用程序在用户态下运行,可以访问系统资源,如文件、网络等。用户态下的应用程序运行在受限的环境中,不能直接访问系统硬件资源,必须通过系统调用来请求内核提供服务。内核态:指操作系统内核运行的环境,在操作系统启动时,内核被加载到内存中,并开始执行。消息机制的功能有以下两种:用户态应用发送消息到驱动。用户态应用接收驱动主动上报事件。驱动消息机制管理消息机制的接口:接口描述structHdfIoService*HdfIoServiceBind(constchar*serviceName)用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息voidHdfIoServiceRecycle(structHdfIoService*service);获取驱动的服务intHdfDeviceRegisterEventListener(structHdfIoService*target,structHdfDevEventlistener*listener);用户态程序注册接收驱动上报事件的操作方法intHdfDeviceSendEvent(structHdfDeviceObject*deviceObject,uint32_tid,structHdfSBuf*data);驱动主动上报事件接口谢谢6.3.2驱动消息机制开发通过本节学习,您可以:了解驱动消息机制开发驱动消息机制开发驱动消息机制的开发步骤:1.修改服务策略policy字段将驱动配置信息中服务策略policy字段设置为2。

device_test::Device{

policy=2;

...

}2.配置驱动信息中的服务设备节点权限配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。驱动消息机制开发3.实现Dispatch方法在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。

//Dispatch是用来处理用户态发下来的消息

int32_tTestDriverDispatch(structHdfDeviceIoClient*device,intcmdCode,structHdfSBuf*data,structHdfSBuf*reply){

HDF_LOGE("testdriverliteAdispatch");

returnHDF_SUCCESS;

}

int32_tTestDriverBind(structHdfDeviceObject*device){

HDF_LOGE("testforliteostestdriverAOpen!");

if(device==NULL){

HDF_LOGE("testforliteostestdriverAOpenfailed!");

returnHDF_FAILURE;

}

static

structITestDriverServicetestDriverA={

.ioService.Dispatch=TestDriverDispatch,

.ServiceA=TestDriverServiceA,

.ServiceB=TestDriverServiceB,

};

device->service=(structIDeviceIoService*)(&testDriverA);

returnHDF_SUCCESS;}驱动消息机制开发4.定义cmd类型驱动定义消息处理函数中的cmd类型。5.获取服务接口并发送消息用户态获取服务接口并发送消息到驱动。#defineTEST_WRITE_READ1//读写操作码1

intSendMsg(const

char*testMsg)

{

if(testMsg==NULL){

HDF_LOGE("testmsgisnull");

returnHDF_FAILURE;

}

structHdfIoService*serv=HdfIoServiceBind("test_driver");

if(serv==NULL){

HDF_LOGE("failtogetservice");

returnHDF_FAILURE;}驱动消息机制开发

structHdfSBuf*data=HdfSBufObtainDefaultSize();

if(data==NULL){HDF_LOGE("failtoobtainsbufdata");

returnHDF_FAILURE;

}

structHdfSBuf*reply=HdfSBufObtainDefaultSize();

if(reply==NULL){HDF_LOGE("failtoobtainsbufreply");

ret=HDF_DEV_ERR_NO_MEMORY;

gotoout;

}

if(!HdfSbufWriteString(data,testMsg)){HDF_LOGE("failtowritesbuf");

ret=HDF_FAILURE;

gotoout;

}

intret=serv->dispatcher->Dispatch(&serv->object,TEST_WRITE_READ,data,reply);

if(ret!=HDF_SUCCESS){HDF_LOGE("failtosendservicecall");

gotoout;

}

out:

HdfSBufRecycle(data);

HdfSBufRecycle(reply);

HdfIoServiceRecycle(serv);

returnret;}驱动消息机制开发6.用户态接收驱动上报的消息用户态编写驱动上报消息的处理函数。

static

intOnDevEventReceived(void*priv,uint32_tid,structHdfSBuf*data)

{

OsalTimespectime;

OsalGetTime(&time);

HDF_LOGE("%sreceivedeventat%llu.%llu",(char*)priv,time.sec,time.usec);

const

char*string=HdfSbufReadString(data);

if(string==NULL){

HDF_LOGE("failtoreadstringineve

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论