二、任务管理

任务管理是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. Python基础(七)-文件操作

    一.文件处理流程 1.打开文件,得到文件句柄赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 二.基本操作 f = open('zhuoge.txt') #打开文件 first_line = ...

  2. Oracle 字符集小结(遇到一例子:查询结果列标题为汉字,但是显示为‘?')

    问题处理方式: 查询:select userenv('language') from dual; 对比电脑环境变量NLS_LANG的值与查询结果是否一致,如果不一致,修改电脑环境变量NLS_LANG ...

  3. WSAEventSelect IO复用模型

    1 今天帮一学习WSAEventSelect的网友排查一个测试用服务器端recv返回0的问题,出现这个问题直观判断一般是客户端socket关闭了,可是他的代码很简单并且是本机测试,通过wireshar ...

  4. 安装mysql的遇到的问题

    源:安装用的是mysql官网的binary包. 之前装mysql都是直接放到/usr/local,就想试试放到其他地方,然后..就悲剧了. 安装步骤没啥说的,官网上有.因为放置的位置不一样所以有些执行 ...

  5. history对象 back() forward() go() 和pushState() replaceState()

    History(Window.history对象)对象保存着用户上网的历史记录.处于安全方面的考虑,开发人员无法得知用户浏览过的URL,但是借由用户访问过的页面列表,同样可以在不知道实际URL的情况下 ...

  6. 二十七、oracle 例外

    一.例外分类oracle将例外分为预定义例外.非预定义例外和自定义例外三种.1).预定义例外用于处理常见的oracle错误.2).非预定义例外用于处理预定义例外不能处理的例外.3).自定义例外用于处理 ...

  7. linux虚拟机正常安装完成后获取不到IP的解决办法

    通常正常情况下安装完linux虚拟机,只需要使用桥接并修改配置文件/etc/sysconfig/network-scripts/ifcfg-eth0,将如下参数值改为如下: ONBOOT=yes NM ...

  8. 【第三篇】Volley图片加载之NetworkImageView代码分析

    在Volley的使用之加载图片讲过使用NetWorkImageView进行图片加载的例子,本文着重讲解NetWorkImageView内部是如何实现的,以及Volley这个控件有什么特性.   1,通 ...

  9. team viewer - rollback framework could not be initialized

    rollback framework could not be initialized, 在安装team viewer 的时候出现的这个错误信息,求大师帮忙 https://zhidao.baidu. ...

  10. cookie模拟

    1        为什么要使用cookie模拟          从日常项目测试过程中的问题说起. 比如要进行论坛中的文件下载功能的测试.我们都知道只有登录用户才能进行下载操作,这样我们的测试过程可能 ...