梅科尔工作室——华为14天培训第二、三章(内核开发)

网友投稿 643 2022-09-05

梅科尔工作室——华为14天培训第二、三章(内核开发)

梅科尔工作室——华为14天培训第二、三章(内核开发)

补充第二章

三、编译构建介绍

1.Ninja简介

Unix/Linux下一般使用Makefile,缺点:编译较慢。

Google重新开发一套编译工具,Ninja,优点:编译速度快。

因此,OpenHarmony采用Ninja进行编译。

2.如何编译模块(流程)

首先,在VS Code终端中输入以下,进入服务器

找到源码目录,执行编译命令

编译完成。

3.编译的过程

json文件:描述了编译的路径,通过路径指向,找到编译文件下的BUILD.gn,将要编译的.c文件编译成.a(下图为BUILD.gn编译的libmyled.a文件)

libmyled.a编译进代码的过程——链接.a文件,然后把它编译成bin文件(二进制文件)。

即:通过json文件去定义要有哪些.c需要去编译成.a文件,然后链接.a文件,编译成bin文件,然后把bin文件烧录到开发板中就可以运行了。

代码是如何运行起来的?

harmonyOS中没有main.c文件,但是可以在以下路径中找到app_main.c文件,即代码从这里开始运行,从运行的日志中也可以看出来。

该app_main.c文件的最后会执行HOS_SystemInit();

找到该段代码,注释掉service,再编译hello world案例,烧录,观察现象。

并没有输出hello world

找到注释掉的函数,顺着函数继续找

下面的name为前面SYS_INIT()中传进来的参数

因此,输出的结果会形成".zinitcall.sys.service2.init"的一个代码段

该指针指向以上代码段的一个地址

通过SYS_INIT()函数往下找

找到LAYER_INITCALL_DEF()函数

在编译时,它会把Init放入刚才的代码段中,因此它会去执行Init函数

顺着Init()函数中的MessageHandle去找

该函数的写法和前面的也是一样的

最终还是会执行下面这段函数,结果为箭头所示

而该段的函数是由Hello World文件中的APP_FEATURE_INIT()函数添加”Hello World"进来的,继续上面的顺序去寻找可以验证。

即:最终编译时,它会把Hello World编译到代码段里面,电脑在运行时,会从该代码段里的指针(指向Hello World)去执行,结果Hello World运行好了。

四、OpenHarmony CMSIS接口简介

1.CMSIS-RTOS2接口简介

2.鸿蒙与CMSIS-RTOS2接口联系

找到.c文件(该文件中做了以上的适配工作)

3.如何使用CMSIS-RTOS2接口

在代码头文件包含"cmsis_os2.h",通过调用"cmsis_os2.h"中API函数使用相关功能。

API介绍链接:​​Main Page (arm-software.github.io)​​

第三章 内核开发

1.任务管理

概念

任务状态

相关概念

创建任务接口

实例

参数设置完之后,通过osThreadNew函数把参数传递进去,创建任务1、2

注:这样创建的函数,优先级是一样的,这时先创建的先运行。

结果,任务1(延时1秒)运行一次,任务2(延时0.5秒)运行两次

然后编译代码,使用HiBurn工具把编译的bin文件烧录到开发板中,结果如图。

扩展实验:

高优先级的任务(ThreadHi,25)会先于低优先级(ThreadLo,14)的任务运行,等高优先级任务被挂起,低优先级任务才会运行,最后两个任务都删除退出。

修改代码:更改优先级,数字越大,优先级越高。

获取任务ID:

1.定义两个变量

2.在创建任务时获取ID

继续实验:

3.理解并修改代码

注释掉(禁止)该函数

5.禁止之后,需要用SYS_RUN启动代码

继续编译,烧录,结果如图。

2.软件定时器

基本概念

软件定时器不受硬件限制,功能与硬件定时器类似

软件定时器运作机制

软件定时器的创建

然后把该案例打开,把其他的屏蔽掉

打开刚才屏蔽掉的

编译,烧录,结果如图

扩展实验:

主要验证:停止定时器和删除定时器

继续编译,烧录,结果如图

原因

其中,不管定时器有没有停止,都是可以执行删除定时器的操作的,即删除定时器是可以随时运行的,不受影响。

3.信号量

基本概念:是一种实现任务间通信的机制,实现任务之间同步或临界资源的互斥访问。

信号量为空时,任务阻塞,调整信号量,相当于调整了任务状态。

用作互斥时:信号量创建后记数是满的,在需要使用临界资源时,先取信号量,使其变空,这样其他任务需要使用临界资源时就会因为无法取到信号量而阻塞,从而保证了临界资源的安全。

用作同步时:信号量在创建后被置为空,任务1取信号量而阻塞,任务2发生某种条件后,释放信号量,于是任务1得以进入READY或RUNNING态,从而达到了两个任务间的同步。

运作原理

1.信号量初始化

为配置的N个信号量申请内存,并把所有的信号量初始化成未使用,并加入到未使用链表中供系统使用。

2.信号量创建

从未使用链表中获取一个信号量资源,并设定初值。

3.信号量申请

若计数器值>0,则减1返回成功。否则任务阻塞,等待其他任务释放该信号量,等待的超时时间可以设定。

4.信号量释放

若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。

5.信号量删除

将正在使用的信号量重置为未使用信号量,并挂回到未使用链表。

6.信号量允许多个任务在同一时刻访问统一资源。

代码实操,结果为每隔一秒,同时打印两行(结果1)。如果前面只释放一次信号量,则每隔一秒,两行代码交替打印(结果2)。

结果1

结果2

信号量释放与信号量申请之间的关系:每释放一次信号量,信号量计数器的计数值会加一,每申请一次会减一,能不能申请到,取决去计数值是否大于0,如果大于,则可以申请。

4.事件管理

概念:事件是一种实现任务间通信的机制,可以用于实现任务间的同步,但事件通信只能是事件类型的通信,无数据传输。

一个任务可以等待多个事件的发生。

事件集合用32位无符号整型变量来表示,每一位代表一个事件。

事件可以提供一对多,多对多的同步操作。

LiteOS的事件仅用于任务间的同步。

事件运作机制如下图所示。

事件接口如图

首先,创建事件,得到事件的id,创建两个任务,其中一个一直等待事件id的标记(永久等待),使用事件标记函数对传入id的任务发送一个标记,然后接收任务运行,继续进行永久等待。

结果,任务1每一秒输出一次接收任务的内容,通过发送事件同步了接收事件。

即:实现了一个事件来同步一个任务。

同理,也可以进行多个事件同步多个任务。

5.互斥锁

基本概念:互斥型信号量,是一种特殊的二值性信号量(开锁或闭锁)。

当任务持有时,互斥锁处于闭锁状态;当任务释放时,互斥锁背开锁。

当一个任务持有互斥锁时,其他任务不能再对该互斥锁开锁或持有。

作用:用于实现对共享资源的独占式处理,可以解决信号量存在的优先级翻转的问题。

LiteOS提供的互斥锁的优点:通过优先级继承算法,解决优先级翻转问题。

互斥锁运作机制

互斥锁接口如图:

代码实操:

首先,创建三个优先级不同的任务(高、中、低),其中高、中级的任务延时一秒钟再获取互斥锁,低优先级不延时,直接获取互斥锁之后延时三秒。

结果:低优先级任务先打印一次,延时三秒,再运行中优先级,然后是低优先级。

结论:任务优先级高,也无法抢占互斥锁持有的任务。

6.消息队列

概念:是一种常用于任务间通信的数据结构,实现了接收来自任务或中断的不固定长度的消息,并根据不同的接口选择传递消息是否存放在自己空间。

任务能够从队列里面读取消息,当队列中消息为空,挂起读取任务,当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。

作用:消息队列提供了异步处理机制,允许一个消息放入队列,但不立即处理它,还能起到缓冲消息的作用。

LiteOS中使用队列数据结构实现任务异步通信工作的特点:

运作原理:

创建队列时,根据用户传入队列长度和消息节点大小来开辟相应的内存空间以供该队列使用,返回队列ID。

消息队列接口如下图

代码实操:

创建消息队列,返回一个id,创建两个任务(分别调用发送消息接口、获取消息接口),并给出相应的提示。

结果:接收消息的接口已经接收到消息,并且以一秒打印一次打印出来。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MySQL两千万数据优化&迁移(mysql一千万条数据优化)
下一篇:[leetcode] 145. Binary Tree Postorder Traversal
相关文章

 发表评论

暂时没有评论,来抢沙发吧~