6. 面向任务程序设计(TOP).

Slides:



Advertisements
Similar presentations

Advertisements

2 和 5 的倍数的特征 运动热身 怎样找一个数的倍数? 从小到大写出 2 的倍数( 10 个): 写出 5 的倍数( 6 个) 2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18 , 20 5 , 10 , 15 , 20 , 25 , 30.
2.5 函数的微分 一、问题的提出 二、微分的定义 三、可微的条件 四、微分的几何意义 五、微分的求法 六、小结.
7.1 内置对象概述及分类 JSP 视频教学课程. JSP2.2 目录 1. 内置对象简介 1. 内置对象简介 2. 内置对象分类 2. 内置对象分类 3. 内置对象按功能区分 3. 内置对象按功能区分 4. 内置对象作用范围 4. 内置对象作用范围.
阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
Oracle数据库 Oracle 子程序.
第五章 C/OS-II在ARM系统中的应用与开发
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
全国计算机等级考试 二级基础知识 第二章 程序设计基础.
在PHP和MYSQL中实现完美的中文显示
陈香兰 助教:陈博、李春华 Spring 2009 嵌入式操作系统 陈香兰 助教:陈博、李春华 Spring 2009.
Kvm异步缺页中断 浙江大学计算机体系结构实验室 徐浩.
4.3函数 4.3.1函数的概念及定义 1、函数的概念: 可以被其它程序调用具有 特定功能的一段相对独立的 程序(模块),称函数。
嵌入式操作系统ucOS-II分析.
UcOS-II任务管理.
UCOS -II的使用 撰写:李湧 2006-06-29.
《手把手教你学STM32-UCOS》 主讲人 :正点原子团队 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司
走进编程 程序的顺序结构(二).
辅导课程六.
网络常用常用命令 课件制作人:谢希仁.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
嵌入式系统 —嵌入式实时操作系统C/OS-Ⅱ分析 2006年5月.
计算机数学基础 主讲老师: 邓辉文.
Online job scheduling in Distributed Machine Learning Clusters
本节内容 模拟线程切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
《手把手教你学STM32》 主讲人 :正点原子团队 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司 淘宝店铺:
ΜC/OSⅡ中的任务调度 Group01小组 柴永锋 李逢春 苗 冬.
UcOS-II时间管理.
CPU结构和功能.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
第一章 函数与极限.
3. µC/OS-II内核 2019/4/11.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
内容摘要 ■ 课程概述 ■ 教学安排 ■ 什么是操作系统? ■ 为什么学习操作系统? ■ 如何学习操作系统? ■ 操作系统实例
C语言程序设计 主讲教师:陆幼利.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
5. µC/OS-II应用实例.
实验四、TinyOS执行机制实验 一、实验目的 1、了解tinyos执行机制,实现程序异步处理的方法。
实验七 安全FTP服务器实验 2019/4/28.
Ch6. uC/OS-II分析 宋健建 南京大学软件学院.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
信号量(Semaphore).
第4章 Excel电子表格制作软件 4.4 函数(一).
iSIGHT 基本培训 使用 Excel的栅栏问题
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
Visual Basic程序设计 第13章 访问数据库
学习任务三 偏导数 结合一元函数的导数学习二元函数的偏导数是非常有用的. 要求了解二元函数的偏导数的定义, 掌握二元函数偏导数的计算.
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
临界区问题的硬件指令解决方案 (Synchronization Hardware)
OpenStack vs CloudStack
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第二节 函数的极限 一、函数极限的定义 二、函数极限的性质 三、小结 思考题.
正弦、余弦函数的性质 华容一中 伍立华 2017年2月24日.
本节内容 Windows线程切换_时钟中断切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
_01自己实现简单的消息处理框架模型 本节课讲师——void* 视频提供:昆山爱达人信息技术有限公司
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
《手把手教你学STM32-UCOS》 主讲人 :正点原子团队 硬件平台:正点原子STM32开发板 版权所有:广州市星翼电子科技有限公司
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
第8章 创建与使用图块 将一个或多个单一的实体对象整合为一个对象,这个对象就是图块。图块中的各实体可以具有各自的图层、线性、颜色等特征。在应用时,图块作为一个独立的、完整的对象进行操作,可以根据需要按一定比例和角度将图块插入到需要的位置。 2019/6/30.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
Presentation transcript:

6. 面向任务程序设计(TOP)

6. 面向任务程序设计(TOP) 程序设计方法 任务与函数 任务构造方法 任务优先级与堆栈 任务调度与切换 任务间同步与通信 任务挂起与恢复

任务种类与关系图

6.1 程序设计方法 程序设计方法最重要的指导思想是模块化设计的思想。在早期面向过程的程序设计中,模块化体现为将要实现的工作编写为一个个的函数,供应用程序调用;在面向对象的程序设计中,模块化体现为将要实现的工作封装为一个个集成了数据和方法的对象(即类定义的变量),程序的执行体现为每个对象的方法执行。

6.1p01 任务与对象的属性对比 属性 任务 对象 数据结构 具有专属于任务的变量,当任务运行时,这些变量位于内存中;当任务处于非执行态时,这些变量处于堆栈中 对象具有私有、保护和公有三种类型的变量,对像存活期间这些变量均有效;对象被删除后,这些变量消失 函数(或方法) 任务中可以调用任何函数,对于不可重入型函数,应使用信号量保护;任务本身对应着一个函数,任务变量就是这个函数的局部变量 对象只能使用定义它的类中的函数、友元函数、继承函数或公有函数,属于对象的函数称为对象的实现方法,简称方法;对象包含很多函数

6.1p02 心电测试仪功能分解

6.2 任务与函数 函数是完成特定功能的一组代码集合,包括函数声明和函数体,具有一个返回值和参数列表,典型的C函数样式为: 返回类型 函数名(参数列表){ 语句组;} 其中,函数名首字符必须为字母或下划线,可返回任意数据类型,如果返回类型为void,则表示无返回值;参数列表中的参数可为任意个或任意类型,如果没有参数列表,默认为void型,即空参数类型。语句组为函数执行的功能,即函数体,需要用花括号括起来。

6.2p01 函数示例(1) 1 void LEDoff(void) 2 { 3 unsigned int val; 4 val=GPCDAT; 5 GPCDAT = (val | 0xE0); 6 }

6.2p02 函数示例(2) 8 INT8U LED_Flash(INT8U u) //LED Flash 9 { 10 INT32U val; 11 val=GPCDAT; 12 switch(u) 13 { 14 case 1: 15 GPCDAT = val ^ 0x0020; // LED1 Flash 16 break; 17 case 2: 18 GPCDAT = val ^ 0x0040; // LED2 Flash 19 break; 20 case 3: 21 GPCDAT = val ^ 0x0080; // LED3 Flash 22 break; 23 default: 24 GPCDAT = val ^ 0x00E0; // LED1,2,3 Flash 25 break; 26 } 27 return(1); 28 }

6.2p03 任务对应的函数必须具有的特点 (1) 函数返回值为空,即返回类型为void,或无返回值。 (2) 函数参数为void *类型,且只能有一个该类型参数。 (3) 函数中有一个无限循环,即死循环。 (4) 死循环中必需出现延时等待、请求事件(或删除任务自己)的语句。

6.2p04 任务举例 1 void AppTask_1(void *pdata) 2 { 3 INT8U err; 4 5 OSTaskNameSet(OS_PRIO_SELF,"AppTask_1",&err); 6 for(;;) 7 { 8 LED_Flash(1); 9 10 OSTimeDlyHMSM(0,0,1,0); 11 } 12 }

6.2p05 创建任务示例(1) 1 OSTaskCreateExt(AppTaskStart, 2 (void *)0, 3 &AppTaskStartStk[TASK_START_STK_SIZE-1], 4 AppTaskStartPrio, 5 AppTaskStartID, 6 &AppTaskStartStk[0], 7 TASK_START_STK_SIZE, 8 (void *)0, 9 OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

6.2p06 创建任务示例(2) 11 OSTaskCreate(AppTask_1, 12 (void *)0, 13 &AppTask_1_Stk[TASK_STK_SIZE-1], 14 AppTask_1_Prio);

6.2p07 µC/OS-II系统中的任务“注册”信息

6.2p08 任务与函数的关系(1) 属性 任务(或任务函数) 普通函数 基本要素 任务函数、优先级、堆栈 函数声明、函数体 函数返回值 任务函数返回值必须为空 返回值可为任意类型 函数参数 任务函数参数必须为void *类型,且只有一个该类型参数 形式参数可以为任意类型,且可以有任意多个 函数中有无死循环 任务函数中必须有死循环 不能有死循环 函数中能否调用系统服务 任务函数可以调用系统服务 当普通函数被任务函数调用时,才能使用系统服务函数 有无独立堆栈 具有独立的堆栈 使用公共堆栈

6.2p09 任务与函数的关系(2) 函数个数有无限制 用户任务函数最多253个 可以为任意多个 函数创建方法 使用OSTaskCreate或OSTaskCreateExt系统函数创建任务 指定函数原型和语句组创建 函数间数据交互 任务函数间使用事件进行数据通信 普通函数间使用指针或全局变量进行数据交互 函数工作状态 任务有五种工作状态,即休眠态、就绪态、等待态、运行态和中断态 普通函数只有休眠态、运行态和中断态三种 是否被系统调度 具有优先级,参与系统调度,总使得最高优先级就绪任务得到执行,其他状态的任务对系统内核可见 被调用时执行,调用完成后对应用程序不可见

6.3 任务构造方法 针对博创UP-CPU2410实验平台上的三个LED灯,要求实现这三个LED灯循环闪烁的功能。基于µC/OS-II系统可以有三种实现方法:其一为创建一个指示层任务;其二为创建三个输入输出层任务;其三为创建计算层和输入输出层任务共同实现。

6.3p01 指示层任务设计过程(1) 首先,为该任务指定优先级。由于系统中指示层任务属于完成附加功能的任务,所以其优先级往往较低,但必须比系统的统计任务和空闲任务要高,因此,可根据需要指定其为接近于空闲任务优先级号的数值。如果空闲任务在系统中的优先级为63,则可指定该指示层任务优先级为小于59但接近59的数值。

6.3p02 指示层任务设计过程(2) 然后,为该任务创建堆栈。堆栈是使用内存的主要单位,一般地,堆栈的大小应为根据程序推算出来的堆栈大小的1.2~1.3倍,甚至更大,这样可有效地解决不可预测的临时中间变量造成的堆栈消耗。对于指示层任务,由于其处理的工作简单,中间变量少或没有,堆栈不应指定过大,以避免浪费。

6.3p03 指示层任务设计过程(3) 最后,为该指示层任务创建函数。该任务函数的功能为每1秒依次循环点亮各个LED灯,根据实现的功能要求,函数体应包括点亮LED灯的语句和系统延时函数。

6.3p04 任务函数 AppTask_1 1 void AppTask_1(void *pdata) 2 { 3 INT8U err; 4 INT8U i; 5 i=1; 6 OSTaskNameSet(OS_PRIO_SELF,"AppTask_1",&err); 7 for(;;) 8 { 9 LEDon(i); 10 i++; 11 if(i>3) 12 i=1; 13 OSTimeDlyHMSM(0,0,1,0); 14 } 15 }

6.3p05 和创建任务AppTask_1相关的操作(1) (1) 创建该任务的堆栈。 #define TASK_STK_SIZE 300 OS_STK AppTask_1_Stk[TASK_STK_SIZE]; (2) 定义该任务的优先级和识别号。 #define AppTask_1_Prio 6 #define AppTask_1_ID 1

6.3p06 和创建任务AppTask_1相关的操作(2) (3) 定义任务扩展数据结构(这一步根据需要设定)。 #define N_TASKS 7 typedef struct { INT8S TaskName[30]; //Task's name INT32U TaskCtr; //Run times INT32U TaskExecTime; //Need a Timer, describe later }TASK_USER_DATA; TASK_USER_DATA TaskUserData[N_TASKS];

6.3p07 和创建任务AppTask_1相关的操作(3) (4) 调用OSTaskCreateExt函数创建任务。 strcpy((char *)TaskUserData[AppTask_1_ID].TaskName,"Task_1"); OSTaskCreateExt(AppTask_1, (void *)0, &AppTask_1_Stk[TASK_STK_SIZE-1], AppTask_1_Prio, AppTask_1_ID, &AppTask_1_Stk[0], TASK_STK_SIZE, &TaskUserData[AppTask_1_ID], OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); (5) 创建任务函数体,如程序段S7-4所示的函数AppTask_1。

6.3q01 输入输出层任务设计(1) 实现三个LED灯循环闪烁的第二种任务设计方法,是把每个LED灯的亮灭视为一个任务,这样三个LED灯的工作状态变化需要三个独立的任务完成,这三个任务的功能在于控制外设(这里是LED灯的亮灭),因此,可称为输入输出层任务。

6.3q02 任务函数 AppTask_1、AppTask_2和AppTask_3(1) 1 void AppTask_1(void *pdata) 2 { 3 INT8U err; 4 5 OSTaskNameSet(OS_PRIO_SELF,"AppTask_1",&err); 6 for(;;) 7 { 8 LEDon(1); 9 OSTimeDlyHMSM(0,0,3,0); 10 } 11 }

6.3q03 任务函数 AppTask_1、AppTask_2和AppTask_3(2) 13 void AppTask_2(void *pdata) 14 { 15 INT8U err; 16 17 OSTaskNameSet(OS_PRIO_SELF,"AppTask_2",&err); 18 for(;;) 19 { 20 OSTimeDlyHMSM(0,0,1,0); 21 LEDon(2); 22 OSTimeDlyHMSM(0,0,2,0); 23 } 24 }

6.3q04 任务函数 AppTask_1、AppTask_2和AppTask_3(3) 26 void AppTask_3(void *pdata) 27 { 28 INT8U err; 29 30 OSTaskNameSet(OS_PRIO_SELF,"AppTask_3",&err); 31 for(;;) 32 { 33 OSTimeDlyHMSM(0,0,2,0); 34 LEDon(3); 35 OSTimeDlyHMSM(0,0,1,0); 36 } 37 }

6.3r01 计算层和输入输出层任务联合设计(1) 把控制三个LED灯的亮灭的任务视为输入输出层任务,而把三个LED灯亮灭的工作方式视为计算层任务,这时需要创建二个任务,且这二个任务间要进行数据同步和通信。这里采用的方法为:计算层任务每隔1秒执行一次,向输入输出层任务释放消息邮箱;输入输出层任务请求到消息邮箱后得到执行,然后提取消息值,根据得到的消息选择控制方式,使三个LED灯循环闪亮。

6.3r02 任务AppTask_1和AppTask_2(1) 1 OS_EVENT *LedShineMbox; 2 void AppTask_1(void *pdata) 3 { 4 INT8U err; 5 INT8U iStyle; 6 iStyle = 1; 7 LedShineMbox=OSMboxCreate(NULL); 8 OSEventNameSet(LedShineMbox,"Led Shine",&err); 9 10 OSTaskNameSet(OS_PRIO_SELF,"AppTask_1",&err); 11 for(;;) 12 { 13 switch(iStyle) 14 {

6.3r03 任务AppTask_1和AppTask_2(2) 15 case 1: 16 OSMboxPost(LedShineMbox,(void *)1); 17 break; 18 case 2: 19 OSMboxPost(LedShineMbox,(void *)2); 20 break; 21 case 3: 22 OSMboxPost(LedShineMbox,(void *)3); 23 break; 24 } 25 iStyle++; 26 if(iStyle>3) 27 iStyle=1; 28 OSTimeDlyHMSM(0,0,1,0); 29 } 30 }

6.3r04 任务AppTask_1和AppTask_2(3) 32 void AppTask_2(void *pdata) 33 { 34 INT8U err; 35 void *pmsg; 36 37 OSTaskNameSet(OS_PRIO_SELF,"AppTask_2",&err); 38 for(;;) 39 { 40 pmsg=OSMboxPend(LedShineMbox,0,&err); 41 LEDon((INT32U)((void *)pmsg)); 42 } 43 }

6.4 任务优先级与堆栈 任务有三个要素,即任务先级、任务堆栈和任务函数,设计任务只需要设计任务的三个要素。 任务优先级号是任务的标识符,用于唯一地标识一个任务;任务识别号(ID号)没有实际意义。 每个任务必须具有自己独立的堆栈,不同任务的堆栈大小可以不同。

6.4p01 优先级号的取值范围 优先级号的数值不能随意指定,os_cfg.h文件中的宏常量OS_LOWEST_PRIO是最大的优先级号数值,如果 #define OS_LOWEST_PRIO 254 则优先级号最大取值为254,由于µC/OS-II系统内部的统计任务和空闲任务要占用二个优先级号,所以,用户任务的最大优先级号数值为OS_LOWEST_PRIO-2。最小优先级号数值为0。优先级号数值越小,任务的优先级越高,因此,优先级号为0的任务优先级最高。

6.4p02 任务个数与优先级号的关系 在os_cfg.h中还有另外一个宏常量OS_MAX_TASKS,该宏常量定义用户应用程序中最大任务数。 如果宏常量OS_MAX_TASKS的值定义为20,即 #define OS_MAX_TASKS 20 除去三个系统任务(空闲任务、统计任务和定时器任务)外,用户最多创建的用户任务为17个,这17个任务的优先级号必须为0~OS_LOWEST_PRIO-2中的17个不同数值。

6.4p03 任务优先级号的分配原则 任务的重要性与其实现的功能密切相关 一般地,那些指示层的任务,由于提供系统运行状态的信息,不需要严格的实时性,故其优先级应设为所有用户任务中最低的。 计算层任务对数据进行处理,对于大数据量的处理,计算层任务会占用较多的CPU时间;输入输出层任务一般仅对内存地址进行操作,必须有严格的时序关系,占用CPU时间较少,并且,输入输出层任务常配合中断服务程序工作。因此,计算层和输入输出层任务的优先级的指定采用规律:输入层任务的优先级高于计算层任务的优先级,计算层任务的优先级高于输出层任务的优先级。

6.4p04 任务及其应用程序抽象描述

6.5 任务调度与切换 任务调度是指从就绪的所有任务中找出优先级最高的任务,使其获得CPU使用权而执行;任务切换是指CPU从一个任务转到为另一个任务服务的过程。当中断服务程序获得CPU使用权,而后中断服务程序执行完后,将发生任务调度,如果被中断的任务的优先级低于就绪的最高优先级任务,则发生任务切换;如果被中断的任务的优先级高于就绪的最高优先级任务,则不发生任务切换,仍然恢复被中断的任务执行。因此,任务调度不一定会发生任务切换,但是任务切换一定会伴随着任务调度。

6.5p01 什么情况下发生任务调度?(1) (1) 当开启多任务时,即调用OSStart函数时。 (2) 当新建一个新任务时,即调用OSTaskCreate或OSTaskCreateExt函数时(必须开启多任务功能)。 (3) 当中断返回时,即调用OSIntExit函数时。 (4) 当任务执行过程中遇到延时函数时,即调用OSTimeDly或OSTimeDlyHMSM时。 (5) 当任务请求事件而得不到时,即调用OSSemPend、OSMboxPend、OSFlagPend、OSMutexPend、OSQPend、OSEventPendMulti等函数而请求不到事件时。

6.5p02 什么情况下发生任务调度?(2) (6) 当任务释放事件且有某个任务正在请求该事件时(µC/OS-II似乎不支持抢占式调度,即如果某个优先级高的任务在请求该事件,也要等释放该事件的任务执行完后再调度),即调用OSSemPost、OSMboxPost、OSMboxPostOpt、OSMutexPost、OSQPost、OSQPostFront、OSQPostOpt和OSFlagPost函数时。 (7) 当任务被挂起或恢复时,即调用OSTaskSuspend或OSTaskResume函数时。 (8) 当任务被删除时,即调用OSTaskDel函数时。 (9) 当任务延时被取消时,即调用OSTimeDlyResume函数时。 (10) 当调用系统时钟节拍函数时,即调用OSTimeTick函数时。

6.5p03 任务调度器的CPU时间 无论操作系统本身设计得多么出色,任务调度和切换都是与应用程序无关的代码,这部分代码越少,操作系统直接使用CPU的时间就越少,从而应用程序得到尽可能多的CPU时间。此外,任务调用和切换时间应该是固定的,不应随任务数量的多少而变化,这样才能准确计算各个用户任务的CPU使用时间。

6.5p04 任务函数中必需包含调度因素 作为任务的要素的任务函数中,必须包含至少一个能使任务发生调度的函数,即上述10种情况下的函数之一,例如延时函数和请求与释放事件函数等,否则调度器无法调度任务。

6.6 任务间同步与通信 如果某个任务按另一个任务的执行节拍同步执行,则称该任务与另一个任务同步;如果某个任务接收来自另一个任务的信息,称该任务与另一个任务通信。在µC/OS-II中,任务间不但可以单向同步与通信,还可以双向同步与通信,同步与通信的手段是事件。

6.6p01 任务间的事件同步与通信

6.6p02 任务对事件的操作? 任务对事件的主要操作有二种,即请求事件和释放事件。当任务请求事件时,任务从事件容器中找出所需要的事件,如果请求成功,则在任务中解析事件,从事件中分析出有用的信息。当任务释放事件时,首先把要发出的信息打包到事件中,然后,将该事件释放到事件容器中(如果有任务正在请求该事件,则事件直接转移到请求该事件的符合条件的任务中)。

6.7 任务挂起与恢复 任务有一种特殊的等待状态,即挂起状态。通过调用函数OSTaskSuspend可以将正在执行的任务自己或处于就绪态和等待态的其他任务挂起。任务一旦被挂起后,只能由其他的任务调用函数OSTaskResume使被挂起的任务恢复其原来的状态,如果原来处于等待态,则恢复后的任务仍然为等待态,并且继续等待延时时间(注意:挂起状态的任务的延时值在任务被挂起期间会随时钟节拍发生变化;如果某时刻延时值变为0了,任务仍然处于挂起状态,不会就绪);如果原来的任务状态为就绪态或执行态,则恢复后的任务处于就绪态,能否立即执行要视其优先级是否比就绪的其他任务的优先级都要高。

6.7p01 任务挂起的主要用途? 由于任务创建后将永不停息地工作下去,如果想使得某个任务工作一段时间后,暂停一段较长的时间,等到一个新的情况发生后,再使用运行。诸如此类的情况,将使用到任务挂起和恢复功能。 任务挂起后,任务仍然存在,其优先级号不能被新创建的任务使用。

需要掌握的知识点 任务的三要素是什么?任务与函数有何本质区别? 任务可分为哪几种类型,各类任务都有什么特点? 任务在什么时候发生调度?任务调度和任务切换是什么关系?