二、任务管理

任务管理是ucos-ii操作系统的核心内容。这一章大致就以下流程来介绍和总结任务管理的相关知识。

要实现复杂任务管理,必然要定义众多数据来描述任务状态,为了精简,建立了许多不同的数据结构,所以第一步就是了解这些数据结构和构成。为了避免枯燥,我们同时要认识到每一种结构具体起到什么作用,感受其中的精妙之处,这样理解起来就更容易了。

建立完必要的数据结构,程序在OS_TCBInit()中对TCB进行初始化,在OSInit()中对操作系统的其他重要数据结构进行初始化。

操作系统在启动和运行过程中,会调用一系列任务管理相关函数,我们通过对这些函数的功能认识进一步了解任务管理的具体实现。

最后我们会再次梳理任务管理从初始化到运行过程中任务切换的整个流程。

1.要了解的数据结构

1>任务控制块TCB(Task Control Block)

任务控制块是最核心的数据结构,定义为一个结构体,每一个任务对应一个TCB,包含了堆栈指针、下一个TCB指针、事件块指针、任务状态、任务优先级等一系列信息。

2>空闲链表和就绪链表

空闲链表和就绪链表是由各个TCB构成的链表,所有已经创建任务的TCB分配到就绪链表,其他分配到空闲链表,每建立一个任务就从空闲链表取一个TCB给到就绪链表,每删除一个任务就将该任务TCB释放回空闲链表。

3>任务优先级指针表OSTCBPrioTb1[OS_LOWEST_PRIO+1]

即任务优先级指针数组,类型为指向TCB的指针,用来获取某优先级任务对应的TCB地址.例如任务优先级为5,其  TCB地址将存入OSTCBPrioTb1[5]。

4>任务堆栈

每个任务都有自己的堆栈空间,用于任务切换或者响应中断时保存CPU寄存器数据和私有数据。堆栈必须声明为OS_STK类型,并且由连续的内存空间组成。

5>任务就绪表OSRdyTab1[]和就绪组OSRdyGrp

为了快速找到当前就绪任务中最高优先级的任务设置了任务就绪表和就绪组,就绪表中每一位以1表示就绪,0表示未就绪。通过设定好的OSMapTb1[]和OSUnMapTb1[]两个常量数组和既定操作可以快速获取就绪任务中的最高优先级。具体结构如下图所示。

6>初始化

OS_TCBInit():TCB初始化函数,创建任务时会分配一个TCB,并对其进行初始化;

OSInit():操作系统的初始化函数,内部又分为多个子函数,包含了对全局变量,就绪表,就绪组,任务优先级指针表,事件标志组,内存,消息队列等的初始化。

2.主要相关函数简介

1>   OS_TaskCreate()    基本任务创建;

2>   OS_TaskCreateExt() 拓展任务创建;

3>   OSTaskDel ()       删除任务(任务返回并处于休眠状态,而不是删除代码);

4>   OSTaskDelReq()    请求删除任务(一般用于删除任务前释放资源);

5>   OSTaskSuspend()   挂起任务(用来暂时停止任务的执行,将其阻塞掉);

6>   OSTaskResume()   恢复任务(将被挂起的任务恢复到就绪态);

7>   OSTimeTick()      任务调度器,每隔一段时间(如20ms)执行一次;

8>   OS_Sched()        任务切换函数,判断切换条件满足后执行OS_TASK_SW();

9>   OS_TASK_SW()     汇编语言编写,压栈和退栈操作,真正转到新任务执行;

10> OSIntExit() 中断中的任务调度函数,判断切换条件满足后执行OSIntCtxSw()

11> OSIntCtxSw()      与CPU相关,实现中断程序中的任务切换

3. 任务管理和调度流程

任务状态转换如下图所示:

任务通过不同的函数调用以及当前情况在不同状态之间切换。图中创建任务,删除任务与第二节中1> OS_TaskCreate()、2> OS_TaskCreateExt()和3> OSTaskDel ()、4> OSTaskDelReq()相对应,事件等待中包含但不局限于OSTaskSuspend(),任务在等待信号量,邮箱或者系统延时时都会被阻塞进入阻塞态。等待的发生包含但不局限于OSTaskResume(),任务接收到信号量,邮箱以及延时完毕进行任务调度会从阻塞态转到就绪态。

任务运行中被中断打断会进入挂起态,中断服务程序结束后执行任务调度使当前最高优先级的就续任务得到运行。被挂起的任务仍为最高优先级,则返回。

OSTimeTick()为任务调度器,实际上是定时器中断,在每个时间片开始遍历每一个任务,将被设置了时间延时的任务延时时间减1,设置满足条件的任务进入就绪态。在发现有更高优先级的就续任务时则执行一次任务调度。

OS_Sched()执行普通任务切换(任务创建,自我删除和自我阻塞时会进行的任务调度),首先判断切换条件,若ISR未完成,调度器上锁或者当前任务即为最高优先级则不会进行切换。OS_Sched()中OS_TASK_SW()用于保存上下文,实现真正转到新任务执行。

OSIntExit()用于在时钟中断中进行任务调度,类似于OS_Sched()首先判断切换条件,若满足则执行OSIntCtxSw()进行任务切换。OSTimeTick()任务调度器就属于中断方式进行的调度。

空闲任务OS_TaskIdle()(操作系统必须的)和统计任务OS_TaskStart()(非必须)是两个系统两个自带的任务,保证CPU不会无事可干和监控CPU运行情况。

4.总结:

     任务管理从任务控制块TCB等数据结构定义和初始化开始,进一步执行操作系统的初始化。多任务启动后,通过任务创建,删除,挂起,恢复等操作和其他事件信息操作使得任务在不同状态间切换。对于CPU来说,每次状态转换都伴随一次任务调度,内核会选择当前就续任务中最高优先级的任务执行,一直处于动态运转中。

μCos-ii学习笔记2_任务管理的更多相关文章

  1. UC_OS II学习笔记

    是一个可以基于ROM运行的.可裁减的.抢占式.实时.多任务OS内核: 可剥夺型的实时内核在任何时候都运行就绪了的最高优先级的任务. 一个任务,也称作一个线程,是一个简单的程序,该程序可以认为 CPU ...

  2. python学习笔记2_条件循环和其他语句

    一.条件循环和其他语句 1.print和import的更多信息. 1.1.使用逗号输出  //print() 打印多个表达式是可行的,用逗号隔开.       在脚本中,两个print语句想在一行输出 ...

  3. Arria10 SDI II学习笔记

    12G-SDI16是什么意思? 关于 int_vpid_byte1 int_vpid_byte2 int_vpid_byte3 int_vpid_byte4 这些参数是不是如果外部数据有就不需要传输, ...

  4. JS学习笔记2_面向对象

    1.对象的定义 ECMAScript中,对象是一个无序属性集,这里的“属性”可以是基本值.对象或者函数 2.数据属性与访问器属性 数据属性即有值的属性,可以设置属性只读.不可删除.不可枚举等等 访问器 ...

  5. JavaScript学习笔记2_面向对象

    1.对象的定义 ECMAScript中,对象是一个无序属性集,这里的“属性”可以是基本值.对象或者函数 2.数据属性与访问器属性 数据属性即有值的属性,可以设置属性只读.不可删除.不可枚举等等 访问器 ...

  6. Angularjs学习笔记2_添加删除DOM元素

    1.调用element方法     angular.element(html) 把字符串或dom对象转化成一JQuery对象, angular.element(document.getElementB ...

  7. Python学习笔记2_一些小程序

    counts = [98,12,3,4,1,4,9,3821] minNum = min(counts) #print minNum minNum_index = counts.index(minNu ...

  8. C++学习笔记2_函数.函数指针.函数模板

    1. 内联函数void printAB(int a,int b){ cout<<(a)<<(b)<<endl;}int main(void){ for(int i= ...

  9. python学习笔记2_二元运算符和比较运算

    一.二元操作符 a+b : a加b a-b :  a减b a*b :  a乘b a/b : a除以b a//b:a整除以b,表示的是返回a除以b的结果的整数部分,而不是证明了a能被b整除.要证明a能被 ...

随机推荐

  1. double hashing 双重哈希

    二度哈希(rehashing / double hashing) 1.二度哈希的工作原理如下: 有一个包含多个哈希函数(H1……Hn)的集合.当我们要从哈希表中添加或获取元素时,首先使用哈希函数H1. ...

  2. NDEF消息解析实例[转]

      问题:按照NDEF消息格式来解析下列Hex串? D1 02 1F 53 70 91 01 0E 54 02  65 6E 68 65 6C 6C 6F 20 77 6F  72 6C 64 51 ...

  3. Jenkins2.32.1+svn+maven安装配置与构建部署

    这两天学习了一下持久化集成工具Jenkins,在自己的本地搭建一个简单的Jenkins环境. 使用环境:Windows64系统,JDK1.8,eclipse,svn(Windows版本VisualSV ...

  4. 实战荟萃-UI篇

    一. 前言 平时在处理问题的时候,经常会遇到一些奇奇怪怪的问题,今天在这里将其记录下来.这里将会列举几个常用的UI问题进行讲解 二. 导航栏 iOS导航栏绝对是个巨坑.和很多朋友聊天都是自己实现了一套 ...

  5. .net 获取类型的Type类型的几种方法

    一:使用Object基类的GetType()方法 Car car = new Car(); Type carType = car.GetType(); 二:使用typeof操作符 Type carTy ...

  6. bash脚本退出代码解释

    Exit Codes With Special Meanings Table E-1. Reserved Exit Codes Exit Code Number Meaning Example Com ...

  7. Linux下区分物理CPU、逻辑CPU和CPU核数

    ㈠ 概念           ① 物理CPU                             实际Server中插槽上的CPU个数              物理cpu数量,可以数不重复的 p ...

  8. maven 阿里镜像

    <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>al ...

  9. linux下安装php的oracle拓展

    最近要用Php远程连接第三方的oracle数据库,安装oracle拓展搞了好久,终于弄出来了,现在分享出来: 1,注意安装的客户端版本要和服务端的版本一致,不然会有异常 2,安装之前先要下载三个软件: ...

  10. CodeForces 702D Road to Post Office

    答案的来源不外乎于3种情况: 纯粹走路,用时记为${t_1}$:纯粹乘车,用时记为${t_2}$:乘车一定距离,然后走路,用时记为${t_3}$. 但是${t_1}$显然不可能成为最优解. 前两个时间 ...