本章将介绍LiteOS内核中的任务管理模块

1. 基本概念

从系统上来说,任务是资源竞争的最小单元,可以使用或等待CPU的系统资源,独立运行。HUWEI LITEOS可以给用户提供多个任务,实现任务通信和切换。任务管理是LiteOS不可裁剪极小内核的一部分功能,主要支持任务的创建,删除,延迟,挂起,恢复等功能,同时支持锁定和解锁任务调度。支持抢占式调度和时间片轮转。

2. 相关属性

任务状态:

一般来说,一个任务可以具有为几种不同的状态,即就绪态,阻塞态,运行态和结束态,这四种状态之间的转换关系如图所示。

状态之间的转换一般是在以下条件下进行

就绪态→运行态

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

运行态→阻塞态

正在运行的任务发生阻塞(挂起、延时、读信号量等)时,该任务会从就绪队列中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。

阻塞态→就绪态(阻塞态→运行态)

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

就绪态→阻塞态

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

运行态→就绪态

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

运行态→退出态

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

阻塞态→退出态

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

任务ID:是任务在创建之初赋予的标识,系统需要根据任务ID对任务进行具体操作(阻塞,恢复,查询名称等)

任务优先级:决定了执行任务的先后状态,在任务切换时,在就绪表中最高优先级的任务会被执行,LiteOS中任务一共有32个优先级【0-31】,最高优先级为0,最低优先级为31

任务入口函数:新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置。

任务栈:一个任务独占的存储资源空间,一般保存了局部变量,寄存器,函数返回地址等信息

任务上下文:一般指任务运行中的一些资源信息,如寄存器等,在任务因为中断或其他原因发生任务切换时,需要把任务上下文保存在任务栈中,防止其他任务在运行时修改了寄存器的值。

任务控制块TCB:每个任务都会具有,里面包含任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息

初始化:user在创建任务时,会初始化上下文,任务栈,并将任务入口函数放置在相应地址。因此在任务第一次启动进入运行态时,会首先执行任务入口函数。

3. 实例分析

3.1 前提条件

在LiteOS根目录下执行make menuconfig,打开menuconfig图形配置界面,找到kernel/Basic Config/Task,对任务模块进行配置。使能LOSCFG_BASE_CORE_TIMESLICE(任务时间片调度开关),LOSCFG_LAZY_STACK(惰性压栈功能),LOSCFG_BASE_CORE_TSK_MONITOR(任务栈溢出检查和轨迹开关),关闭LOSCFG_TASK_STATIC_ALLOCATION(创建任务时,由用户传入任务栈),将LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO(默认任务优先级)设置为10,其他项保持不变。

3.2 具体步骤

在完成上述准备工作后,就可以在LiteOS Stdio下新建工程开始写程序了,首先在宏定义中定义两个变量和两个不同的优先级,随后分别定义两个优先级任务的入口函数,

注:LOS_TaskDelay是los_task.c中的任务延时函数,其默认返回值为LOS_OK.

UINT32 g_taskHiId;
UINT32 g_taskLoId;
#define TSK_PRIOR_HI 4
#define TSK_PRIOR_LO 5UINT32 Example_TaskHi(VOID)//高优先级任务
{UINT32 ret;printf("Enter TaskHi Handler.\r\n");/* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoId任务) */ret = LOS_TaskDelay(2);if (ret != LOS_OK) {printf("Delay Task Failed.\r\n");return LOS_NOK;}/* 2个Tick时间到了后,该任务恢复,继续执行 */printf("TaskHi LOS_TaskDelay Done.\r\n");/* 挂起自身任务 */ret = LOS_TaskSuspend(g_taskHiId);if (ret != LOS_OK) {printf("Suspend TaskHi Failed.\r\n");return LOS_NOK;}printf("TaskHi LOS_TaskResume Success.\r\n");return ret;
}UINT32 Example_TaskLo(VOID)//低优先级任务
{UINT32 ret;printf("Enter TaskLo Handler.\r\n");/* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(背景任务) */ret = LOS_TaskDelay(2);if (ret != LOS_OK) {printf("Delay TaskLo Failed.\r\n");return LOS_NOK;}printf("TaskHi LOS_TaskSuspend Success.\r\n");/* 恢复被挂起的任务g_taskHiId */ret = LOS_TaskResume(g_taskHiId);if (ret != LOS_OK) {printf("Resume TaskHi Failed.\r\n");return LOS_NOK;}printf("TaskHi LOS_TaskDelete Success.\r\n");return ret;
}

随后我们在测试主函数中引用这两个入口函数

UINT32 Example_TskCaseEntry(VOID)
{UINT32 ret;TSK_INIT_PARAM_S initParam;/* 锁任务调度,防止新创建的任务比本任务高而发生调度 */LOS_TaskLock();printf("LOS_TaskLock() Success!\r\n");initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi;initParam.usTaskPrio = TSK_PRIOR_HI;initParam.pcName = "TaskHi";initParam.uwStackSize = LOSCFG_TASK_MIN_STACK_SIZE;initParam.uwResved   = LOS_TASK_STATUS_DETACHED;/* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ret = LOS_TaskCreate(&g_taskHiId, &initParam);if (ret != LOS_OK) {LOS_TaskUnlock();printf("Example_TaskHi create Failed!\r\n");return LOS_NOK;}printf("Example_TaskHi create Success!\r\n");initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo;initParam.usTaskPrio = TSK_PRIOR_LO;initParam.pcName = "TaskLo";initParam.uwStackSize = LOSCFG_TASK_MIN_STACK_SIZE;initParam.uwResved   = LOS_TASK_STATUS_DETACHED;/* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ret = LOS_TaskCreate(&g_taskLoId, &initParam);if (ret != LOS_OK) {LOS_TaskUnlock();printf("Example_TaskLo create Failed!\r\n");return LOS_NOK;}printf("Example_TaskLo create Success!\r\n");/* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */LOS_TaskUnlock();return LOS_OK;
}

其中,TSK_INIT_PARAM_S是los_task.h中任务管理的一个接口函数,主要是用于对任务进行初始化的,其成员作用如下表所示。而LOS_TaskCreate函数是根据TSK_INIT_PARAM任务属性和任务地址完成任务的最终创建函数,创建成功的返回值也是LOS_OK,在任务创建成功后我们就可以解锁任务调度器,按照就绪队列表的优先级顺序开始对任务进行执行。

pfnTaskEntry

任务入口函数

usTaskPrio

优先级

pcName

任务名称

uwResved

任务在使用结束后的自删除选项

uwStackSize

任务栈的大小

因此在任务测试函数中,首先我们调用LOS_TaskLock函数锁住任务调度功能,防止出现创建任务的优先级高于本任务默认的系统优先级,随后根据两个任务的入口函数对两个任务的属性初始化,然后创建两个任务,将两个任务排入就绪列表中,最后解锁任务调度功能,从就绪队列中开始执行任务。其编译执行结果如下所示

LOS_TaskLock() Success!
Example_TaskHi create Success!
Example_TaskLo create Success!
Enter TaskHi Handler.
Enter TaskLo Handler.
TaskHi LOS_TaskDelay Done.
TaskHi LOS_TaskSuspend Success.
TaskHi LOS_TaskResume Success.
TaskHi LOS_TaskDelete Success.

从中可以看出,在锁住任务调度之后,首先依次执行高低优先级任务的创建函数LOS_TaskCreate,在任务解锁之后,由于TaskHi优先级高,先执行其入口函数,打印首句” Enter TaskHi Handler”后因为延时自身任务被挂起,任务调度随即转到TaskLo的入口函数执行内容,同样执行完首句后,延时2Tick被挂起,任务调度重新转回TaskHi上次切换时的执行位置,打印出” TaskHi LOS_TaskDelay Done”,随后根据程序再度挂起自身,执行TaskLo函数中的printf("TaskHi LOS_TaskSuspend Success.\r\n");语句,随后执行恢复TaskHi语句ret = LOS_TaskResume(g_taskHiId);转到TaskHi入口函数的断点,打印出TaskHi LOS_TaskResume Success.结束TaskHi入口函数的执行,最后转到TaskLo入口的断点执行打印出TaskHi LOS_TaskDelete Success。至此,就绪表中所有任务均执行完成,程序结束。

注:程序中的相关接口函数可以在gitee上的LiteOS仓库找到。

LiteOS内核开发(二)相关推荐

  1. LiteOS内核开发(一)

    之前学习LiteOS内核的基本结构和应用的时候,我们通过一张LiteOS内核系统的结构图了解到其基本结构. 其中,Huawei LiteOS基础内核包括不可裁剪的极小内核和可裁剪的其他模块.极小内核包 ...

  2. mongodb时间范围查询少8个小时_为何要对开源mongodb数据库内核做二次开发

    关于作者 前滴滴出行技术专家,现任OPPO文档数据库mongodb负责人,负责oppo千万级峰值TPS/十万亿级数据量文档数据库mongodb内核研发及运维工作,一直专注于分布式缓存.高性能服务端.数 ...

  3. android 全志a10(2.3.4)开发二(linux内核编译及源码编译)

    <android 全志a10(2.3.4)开发二>文档详细可下载地址:http://www.a10bbs.com/forum.php?mod=viewthread&tid=504& ...

  4. linux内核开发入门二(内核KO模块介绍、开发流程以及注意事项)

    linux内核开发入门二(内核KO模块介绍.开发流程以及注意事项) 一.什么是内核模块 内核模块:ko模块(Kernel Object Module)是Linux内核中的可加载模块,它可以动态地向内核 ...

  5. linux内核(二)内核移植(DM365-DM368开发攻略——linux-2.6.32的移植)

    一.介绍linux-2.6.32: Linux-2.6.32的网上介绍:增添了虚拟化内存 de-duplicacion.重写了 writeback 代码.改进了 Btrfs 文件系统.添加了 ATI ...

  6. 《Linux内核设计与实现》读书笔记(二)- 内核开发的准备

    在尝试内核开发之前,需要对内核有个整体的了解. 主要内容: 获取内核源码 内核源码的结构 编译内核的方法 内核开发的特点 1. 获取内核源码 内核是开源的,所有获取源码特别方便,参照以下的网址,可以通 ...

  7. 一分钟带你了解Huawei LiteOS组件开发指南

    摘要:本文将基于Huawei LiteOS系统,从组件定义开始带你走进组件开发指南. 本文分享自华为云社区<一分钟带你了解Huawei LiteOS之组件开发指南>,作者: Lionlac ...

  8. LiteOS内核源码分析:静态内存Static Memory

    本文分享自华为云社区<LiteOS内核源码分析系列十二 静态内存Static Memory>,原文作者:zhushy . 内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包 ...

  9. harmonyos2.0三大技术特点,科普干货|漫谈鸿蒙LiteOS-M与HUAWEI LiteOS内核的几大不同...

    摘要:鸿蒙和LiteOS的内核都是一样的名字,可它们究竟有什么不同呢?一起来对比一下文件吧! HarmonyOS系统 HarmonyOS是一款"面向未来".面向全场景(移动办公.运 ...

最新文章

  1. Java泛型详解,通俗易懂
  2. android 重置画布,android-自定义视图:重按视图画布
  3. 数据库迁移mysql到sqlserver_数据库迁移(sqlserver至mysql)
  4. covid 19如何重塑美国科技公司的工作文化
  5. leetcode 778. 水位上升的泳池中游泳(并查集)
  6. pthread_cond_t
  7. php如何用session做查询条件,php如何使用session?
  8. 三星电子通信撤出中国!
  9. 计算机应用基础2-excel,《2014计算机应用基础excel2.doc
  10. 【HAVENT原创】VUE2 经验问题汇总
  11. Mac手动关闭暗黑模式
  12. LateX各种命令符号
  13. linux 获取文件名的后缀名,linux shell 取文件名后缀
  14. 中柏pad7安装linux,中柏电脑下载与安装win7iso镜像系统教程
  15. 使用msi2lmp和materials studio导出复杂结构的data文件的报错:Unable to find bond data for XXX,Unable to find oop data
  16. GitLab 中编辑 Markdown 写README技巧
  17. 电脑重装:微PE工具箱重装win10系统
  18. centos7磁盘清理方法
  19. qnx 镜像文件_QNX开发最完整图文教程(官方文档,非官方翻译)
  20. yii通过uc实现同步登陆

热门文章

  1. Flink的窗口计算案例
  2. 李开复最新刷屏演讲:人工智能最难取代这13种工作,也最容易威胁人性与爱!
  3. Unity | 如何使用webm透明视频
  4. matlab中taufft,非线性光纤光学中分步傅里叶算法(SSFFT)的matlab代码实现
  5. (数学建模)2013年国赛B题-碎纸片复原python代码
  6. RealPlayer.11.6.0.14.748 新体验
  7. java 记牌_(笔记)JAVA--集合实现斗地主洗牌、发牌、看牌(利用TreeSet排序)
  8. 【渝粤题库】陕西师范大学100200 信息技术教育应用 作业 (专升本、高起专、高起本)
  9. fiddler抓包工具:生成证书
  10. MTK平台添加虚拟sensor