写点什么

Niobe 开发板:基于 OpenHarmony 操作系统进行多线程 (多任务) 开发

作者:拓维信息
  • 2022 年 5 月 20 日
  • 本文字数:2919 字

    阅读完需:约 10 分钟

Niobe开发板:基于OpenHarmony操作系统进行多线程(多任务)开发

线程的基本概念

从系统角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待 CPU、使用内存空间等系统资源,并独立于其它线程运行。


OpenHarmony LiteOS 可以给用户提供多个线程,实现线程间的切换,帮助用户管理业务程序流程。具有如下特性:


1、支持多线程。

2、一个线程代表一个任务。

3、抢占式调度机制,高优先级的线程可打断低优先级线程,低优先级线程必须在高优先级线程阻塞或结束后才能得到调度。

4、相同优先级线程支持时间片轮转调度方式。

5、共有 32 个优先级[0-31],最高优先级为 0,最低优先级为 31。用户进程可配置的优先级有 22 个 (10~31)。


1.线程的状态


线程有多种运行状态。系统初始化完成后,创建的线程就可以在系统中竞争一定的资源,由内核进行调度。

线程状态通常分为以下四种:

就绪(Ready):该线程在就绪队列中,只等待 CPU。

运行(Running):该线程正在执行。

阻塞(Blocked):该线程不在就绪队列中。包含线程被挂起(suspend 状态)、线程被延时(delay 状态)、线程正在等待信号量、读写队列或者等待事件等。

退出态(Dead):该线程运行结束,等待系统回收资源。


2.线程状态迁移

就绪态→运行态: 任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,同时该任务从就绪队列中移出。

运行态→阻塞态:正在运行的任务发生阻塞(挂起、延时、读信号量等)时,将该任务插入到对应的阻塞队列中,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。

阻塞态→就绪态(阻塞态→运行态):阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态;此时如果被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态。

就绪态→阻塞态 : 任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复。

运行态→就绪态 : 有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中。

运行态→退出态 : 运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态以及 Invalid 状态。例如,任务运行结束但是没有自删除,对外呈现的就是 Invalid 状态,即退出态。

阻塞态→退出态 : 阻塞的任务调用删除接口,任务状态由阻塞态变为退出态。


3.线程管理


对于多线程的场景,HarmonyOS 内核管理线程靠任务池和就绪队列,执行靠调度算法。

调度算法:HarmonyOS 内核中的线程采用抢占式调度机制,同时支持 SCHED_RR 和 SCHED_FIFO 调度策略



RR 策略能基本保证我们每个任务都能够得到有效的执行,不会有一些任务进行长时间等待

FIFO 策略优点在于任务的切换比较简单,而且对于一些时间片不好把握的任务来说,FIFO 能偶更有效的利用我们的 cpu。


线程相关 API

此处介绍 cmsis2.0 的线程接口,头文件:”//third_party/cmsis/CMSIS/RTOS2/Include/cmsis_os2.h”



创建线程

osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
复制代码


函数 osThreadNew 通过将线程添加到活动线程列表并将其设置为就绪状态来启动线程函数。线程函数的参数使用参数指针 argument 传递。当创建的 thread 函数的优先级高于当前运行的线程时,创建的 thread 函数立即启动并成为新的运行线程。线程属性是用参数指针 attr 定义的。属性包括线程优先级、堆栈大小或内存分配的设置。可以在 RTOS 启动(调用 osKernelStart)之前安全地调用该函数,但不能在内核初始化 (调用 osKernelInitialize)之前调用该函数。



开发实例


1.确定目录结构

先在路径./applications/app 下新建一个目录,用于存放业务源码文件。其中“.”表示 OpenHarmony 源码的根目录。例如:在 app 下新增业务 NIOBE_OS_helloworld,其中 hello_world.c 为业务代码,BUILD.gn 为编译脚本,其目录结构如下:

.└── applications    └── app           │── TW002_OS_thread           │    │── os_thread_example.c           │    └── BUILD.gn           └── BUILD.gn
复制代码


2.编写业务代码

#include <stdio.h>#include <string.h>#include <unistd.h>
#include "ohos_init.h"#include "cmsis_os2.h"
/*****任务一*****/void thread_entry1(void){ int sum = 0; while (1) { printf("This is Niobe Thread1----%d\r\n", sum++); usleep(500000); }}
/*****任务二*****/void thread_entry2(void){ int sum = 0; while (1) { printf("This is Niobe Thread2----%d\r\n", sum++); usleep(500000); }}
/*****任务创建*****/static void OS_Thread_example(void){ osThreadAttr_t attr;
attr.name = "thread1"; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 1024 * 4; attr.priority = 25;
if (osThreadNew((osThreadFunc_t)thread_entry1, NULL, &attr) == NULL) { printf("Falied to create thread1!\n"); }
attr.name = "thread2";
if (osThreadNew((osThreadFunc_t)thread_entry2, NULL, &attr) == NULL) { printf("Falied to create thread2!\n"); }}
复制代码


3. 编写将业务构建成静态库的 BUILD.gn

static_library("os_thread_example"){    sources = [        "os_thread_example.c"    ]
include_dirs = [ "//third_party/cmsis/CMSIS/RTOS2/Include" ]}
复制代码


4.编写模块 BUILD.gn 文件

import("//build/lite/config/component/lite_component.gni")
lite_component("app") { features = [ #"NIOBE_OS_helloworld:helloworld", "TW002_OS_thread:os_thread_example" ]}
复制代码


编译

用 docker 编译,进入 OpenHarmony 代码根目录,运行命令进入 docker 镜像,在镜像中用 hb 编译:

sudo docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5   
hb set.
//继续回车选择niobe_wifi_iot
hb build -b release -f
复制代码



等待编译成功


烧录

编译成功后,bin 文件会保存在 out/niobe/niobe_wifi_iot 目录下:


用 HiBurn.exe 将 Hi3861_wifiiot_app_allinone.bin 文件烧录到 niobe 核心板上:

首先用 typeC 线连接电脑和 Niobe 核心板,可通过设备管理确定 Niobe 连接的端口号,该端口号后续 HiBurn 和 sscom 都需要。


再通过 HiBurn.exe 工具将固件烧录到 Niobe 上,HiBurn 工具的获取和操作可参考烧录指导


调试

采用串口调试工具 sscom 查看串口打印信息,先对 sscom 进行配置,设置端口号、波特率等:


点击打开串口,按下 Niobe 核心板上的复位按键,可通过 sscom 看到串口打印日志如下:

This is Niobe Thread1----2This is Niobe Thread2----5This is Niobe Thread1----3This is Niobe Thread2----6
复制代码

可以看到线程 thread_entry1 和线程 thread_entry2 交替运行。


相关工具获取


HiBurnsscom工具获取

发布于: 刚刚阅读数: 2
用户头像

拓维信息

关注

还未添加个人签名 2021.11.30 加入

OpenHarmony生态主要共建单位之一,聚焦OpenHarmony生态产业发展,推动OpenHarmony场景化应用探索

评论

发布
暂无评论
Niobe开发板:基于OpenHarmony操作系统进行多线程(多任务)开发_OpenHarmony_拓维信息_InfoQ写作社区