目录

系列文章目录

前言

一、任务的创建

二、任务的栈空间

三.任务的挂起和恢复

1.挂起任务

2.恢复任务

四.删除任务


系列文章目录

第一章裸机系统与操作系统

第二章操作系统分类

第三章实时操作系统简介

第四章实时操作系统---内核结构

第五章实时操作系统---内核结构2

第六章实时操作系统---中断和时间管理


前言

前面几篇文章我们了解了实时操作系统的主要概念以及内核结构,接下来我们一起看下操作系统的精髓《任务管理》,本章所讲的内容包括如何在用户的应用程序中建立任务、删除任务、改变任务的优先级、挂起和恢复任务,以及获得有关任务的信息。


一、任务的创建

µC/OS-Ⅱ可以管理多达 64 个任务,并从中保留了四个最高优先级和四个最低优先级的任务供自己使用,所以用户可以使用的只有 56 个任务。任务的优先级越高,反映优先级的值则越低。在最新的µC/OS-Ⅱ版本中,任务的优先级数也可作为任务的标识符使用。

μC/OS-I是通过任务控制块来管理任务的。因此,创建任务的工作实质上是创建一个任务控制块,并通过任务控制块把任务代码和任务堆栈关联起来形成个完整的任务。当然,还要使刚创建的任务进入就绪状态,并接着引发一次任务调度。c/os-i有两个用来创建任务的函数: OSTaskCreate和 OSTaskCreateExt(其中OSTaskCreateExt()是 OSTaskCreate()的扩展,并提供了一些附加功能。用户可根据需要使用这两个函数之一来完成任务的创建工作。

任务的创建有以下三个要点

  1. 任务可以在多任务调度开始 (即调用OSStart())之前创建,也可以在其它任务的执行过程中被创建。

  2. 在OSStart()被调用之前,用户必须创建至少一个任务;

  3. 不能在中断服务程序(ISR)中创建新任务

下面是OSTaskCreate的源码

INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U
prio)
{void *psp;INT8U err;if (prio > OS_LOWEST_PRIO) {return (OS_PRIO_INVALID);}OS_ENTER_CRITICAL();if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {OSTCBPrioTbl[prio] = (OS_TCB *)1;OS_EXIT_CRITICAL();psp = (void *)OSTaskStkInit(task, pdata, ptos, 0);err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0);if (err == OS_NO_ERR) {OS_ENTER_CRITICAL();OSTaskCtr++;OSTaskCreateHook(OSTCBPrioTbl[prio]);OS_EXIT_CRITICAL();if (OSRunning) {OSSched();}} else {OS_ENTER_CRITICAL();OSTCBPrioTbl[prio] = (OS_TCB *)0;OS_EXIT_CRITICAL();}return (err);} else {OS_EXIT_CRITICAL();return (OS_PRIO_EXIST);}
}

从上面的源码中,我们可以看到创建任务的过程如下:

  • 任务优先级检查 :该优先级是否在0到OS_LOWSEST_PRIO之间?该优先级是否空闲?

  • 调用OSTaskStkInit(),创建任务的栈帧;

  • 调用OSTCBInit(),从空闲的OS_TCB池(即OSTCBFreeList链表)中获得一个TCB并初始化其内容,然后把它加入到           OSTCBList链表的开头,并把它设定为就绪状态;

  • 任务个数OSTaskCtr加1;

  • 调用用户自定义的函数OSTaskCreateHook();

  • 判断是否需要调度(调用者是正在执行的任务)

返回值

  • OS_NO_ERR:函数调用成功;

  • OS_PRIO_EXIT:任务优先级已经存在;

  • OS_PRIO_INVALID:任务优先级无效。


二、任务的栈空间

每个任务都有自己的栈空间(Stack),栈必须声明为OS_STK类型,并且由连续的内存空间组成;
栈空间的分配方法

  • 静态分配:在编译的时候分配

static OS_STK MyTaskStack[stack_size];  OS_STK MyTaskStack[stack_size];
  • 动态分配:在任务运行的时候使用malloc()函数来动态申请内存空间;

OS_STK *pstk;
pstk = (OS_STK *)malloc(stack_size);
/* 确认malloc()能得到足够的内存空间 */
if (pstk != (OS_STK *)0)
{Create the task;
}

在动态分配中,用户要时刻注意内存碎片问题。特别是当用户反复地建立和删除任务时,内存堆中可能会出现大量的内存碎片,导致没有足够大的一块连续内存区域可用作任务堆栈,这时 malloc()便无法成功地为任务分配堆栈空间。

上图表示了一块能被 malloc()动态分配的 3K 字节的内存堆 。为了讨论问题方便,假定用户要建立三个任务(任务 A,B 和C),每个任务需要 1K 字节的空间。设第一个 1K 字节给任务 A, 第二个 1K 字节给任务 B, 第三个 1K 字节给任务 C。然后,用户的应用程序删除任务 A 和任务 C,用 free()函数释放内存到内存堆中。现在,用户的内存堆虽有 2K 字节的自由内存空间,但它是不连续的,所以用户不能建立另一个需要 2K 字节内存的任务(即任务 D)。如果用户并不会去删除任务,使用 malloc()是非常可行的

栈的增长方向的设置

从低地址到高地址:在OS_CPU.H中,将常量OS_STK_GROWTH设定为 0;

从高地址到低地址:在OS_CPU.H中,将常量OS_STK_GROWTH设定为 1;

OS_STK TaskStack[TASK_STACK_SIZE];   OSTaskCreate(task, pdata,&TaskStack[TASK_STACK_SIZE-1],prio);


三.任务的挂起和恢复

1.挂起任务

所谓挂起一个任务,就是停止这个任务的运行。在uC/OS-Ⅱ中,用户任务可通过调用系统提供 OSTaskSuspend()函数来挂起自身或者除空闲任务之外的其他任务。用函数OSTaskSuspend)挂起的任务,只能在其他任务中通过调用恢复函数 OSTaskResume()使其恢复为就绪状态。任务在运行状态、就绪状态和等待状态之间的转移关系下图所示。

挂起任务函数 OSTaskSuspend()的原型为INT8U OSTaskSuspend (INT8U prio);函数的参数prio为待挂起任务的优先级别。如果调用函数 OSTaskSuspend()的任务要挂起自身,则参数必须为常数s_pIO_SELF(该常数在文件uCOS_II.H中被定义为OxFF)

当函数调用成功时,返回信息 OSNOERR;否则根据出错的具体情况返回OS_TASKSUSPEND_IDLE、OS_PRIO_INVALID和OS_TASK_SUSPEND_PRIO

该函数在一系列的判断中主要是判断待要挂起的任务是否调用这个函数的任务本身。如果是任务本身,则必须删除任务在任
务就绪表中的就绪标志,并在任务控制块成员 OSTCBStat中做了挂起记录之后,引发一次任务调度,以使CPU去运行就绪的其他任务。如果待挂起的任务不是调用函数的任务本身而是其他任务,那么只要删除任务就绪表中被挂起任务的就绪标志,并在任务控制块成员OSTCBStat中做了挂起记录即可。

2.恢复任务

OSTaskResume():

  • 恢复一个任务恢复被OSTaskSuspend()挂起的任务;

  • 清除TCB中OSTCBStat字段OS_STAT_SUSPEND位

函数的参数为待恢复任务的优先级别。若函数调用成功,则返回信息OS_NO_ERR;否则,据出错的具体情况返回OS_PRIO_INVALID、OS_TSK_ RESUME_PRIO和OS_TASK_NOT_SUSPEND等。 OSTaskResume()函数在判断任务确实是一个已存在的挂起任务,同时它又不是一个等待任务(任务控制块成员 OSTCBDly=0)时,就清除任务制块成员 OSTCBStat中的挂起记录并使任务就绪,最后调用调度器 OSSched()进行任务调度,并返回函数调用成功的信息OS_NO_ERR

四.删除任务

所谓删除一个任务,就是把该任务置于睡眠状态。具体做法是,把被删除任务的任务控制圳从任务控制块链表中删除,并归还给空任务控制块链表,然后在任务就绪表中把该任务的就绪状态位置0,于是该任务就不能再被调度器所调用了。简单地说,就是把它的身份证给吊销了。在任务中,可以通过调用函数 OSTaskDel来删除任务自身或者除了空闲任务之外的其他任务。

如果一个任务调用这个函数是为了删除任务自己,则应在调用函数时令函数的参数pri为OS_PRIO_SELF有时,任务会占用一些动态分配的内存或信号量之类的资源。这时,如果有其他任务把这个任务删除了,那么被删除任务所占用的一些资源就会因为没有被释放而丢失,这是任何系统都无法接受的。

因此,在删除一个占用资源的任务时,一定要谨慎。具体的办法是,提出删任务请求的任务只负责提出删除任务请求,而删除工作则由被删除任务自己来完成。这样,被删除任务就可以根据自身的具体情况来决定何时删除自身,同时也有机会在删除自身之前占用的资源释放掉。

显然,如果想使提出删除任务请求的任务和被删除任务之间,能够像上述方式来执行删工作,则它们双方必须有某种通信方法μC/OS-II利用被删除任务的任务控制块成员OSTCBDelReq作为请求删除方的被删除方的联络信号,同时提供了一个双方都能调用的函数请求删除任务函数 OSTaskDelReq()。这样,提出删除任务请求的任务和被删除任务的双方就都使用这个函数来访问 OSTCBDelReq这个信号,从而可以根据这个信号的状态来决定各自的行为。

删除任务请求方要用被删除任务的优先级别prio作为参数来调用这个函数。从图中可以看出,删除任务请求方调用这个函数的目的就是要查看被删除的任务控制块是否还在如果还在,则令被删除任务的任务控制块成员 OSTCBDelReq的值为 OSTaskDelReq且通知该任务:“已经有任务要求在合适的时候要删除自己”;如果不在,认为被删除任务经被删除了。

实时操作系统---任务管理相关推荐

  1. STM32CubeMX学习笔记(28)——FreeRTOS实时操作系统使用(任务管理)

    一.FreeRTOS简介 FreeRTOS 是一个可裁剪.可剥夺型的多任务内核,而且没有任务数限制.FreeRTOS 提供了实时操作系统所需的所有功能,包括资源管理.同步.任务通信等. FreeRTO ...

  2. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十六章 UCOSII 实验 1任务调度...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十六章 ...

  3. 基于STM32的实时操作系统FreeRTOS移植教程(手动移植)

    前言:此文为笔者FreeRTOS专栏下的第一篇基础性教学文章,其主要目的为:帮助读者朋友快速搭建出属于自己的公版FreeRTOS系统,实现后续在实时操作系统FreeRTOS上的开发与运用.操作系统的学 ...

  4. 实时操作系统UCOS学习笔记1----UCOSII简介

    前面我们所有的实验都是跑的裸机程序(裸奔),从本章开始,我们开始介绍UCOSII(实时多任务操作系统内核). UCOSII简介 UCOSII的前身是UCOS,最早出自于1992年美国嵌入式系统专家Je ...

  5. 什么是真正的实时操作系统

    做嵌入式系统开发有一段时间了,做过用于手机平台的嵌入式Linux,也接触过用于交换机.媒体网关平台的VxWorks,实际应用后回过头来看理论,才发现自己理解的肤浅,也发现CSDN上好多同学们都对实时. ...

  6. 嵌入式操作系统和RTOS(实时操作系统)介绍。

    目录 嵌入式操作系统 RTOS(实时操作系统) 实时操作系统: 什么是嵌入式操作系统 一μClinux 二μC/OS-II 三eCos 四 FreeRTOS 五 mbed OS 六 RTX 七 VxW ...

  7. 为什么采用实时操作系统?

    为什么采用实时操作系统? 采用while(1)死循环等待中断的方式,对于不支持抢占式的处理器,很可能因为考量不周而导致中断资源不能及时释放造成中断丢失: CPU频率远大于外设频率,少不了存在大量等待时 ...

  8. stm32中用到的实时系统_基于STM32平台的实时操作系统

    基于STM32平台且满足实时控制要求操作系统,有以下5种可供移植选择,分别为μClinux.μC/OS-II.eCos.FreeRTOS和都江堰操作系统(djyos). 下面分别介绍这五种嵌入式操作系 ...

  9. VxWorks、μClinux、μC/OS-II和eCos实时操作系统大对比

    原文链接:http://www.eetrend.com/forum/100048985 VxWorks.μClinux.μC/OS-II和eCos是4种性能优良并被广泛应用的实时操作系统.本文通过对这 ...

最新文章

  1. 因特网的协议集称为TCP/IP协议集
  2. session和cookie的应用场景和区别
  3. html校验长度为9位,2018记一次前端面试笔试考题一
  4. nginx: [error] invalid PID number in /run/nginx.pid
  5. 【机器学习】Lasso回归(L1正则,MAP+拉普拉斯先验)
  6. python解析多层嵌套json_Python爬虫解析多个嵌套JSON,多级,json
  7. 前端手动封装数组的foreach,map,filter,every,some,Reduce,reduceRight方法
  8. 提高篇 第二部分 字符串算法 第4章 AC自动机
  9. wpf treeview调整子菜单间距_完全由C编写,高度可移植,超级牛逼的菜单架构!...
  10. win7桌面图标计算机打不开,win7系统下双击电脑桌面图标打不开的解决方法
  11. css js 代码怎么隐藏,如何仅使用js代码(和css)隐藏元素?
  12. 11.盛水最多的容器
  13. PHP数组常用方法(优化版)
  14. 我的世界java版伪光影_我的世界光影核心V2伪风光材质包
  15. 怎么提高企业微信加人的通过率,让企业微信加更多客户?快速加人,引流拓客有什么技巧(企微运营干货)
  16. 把内存中的数据传送到计算机硬盘称为,将内存中的数据传送到计算机硬盘的过程称为什么...
  17. 计算机科学与技术有剪辑吗,计算机科学与技术学院第七届“微剪辑大赛”
  18. 如何找靠谱的游戏开发外包公司
  19. Vue错误03:Property or method “xxx“ is not defined on the instance but referenced during render.
  20. string的insert的用法整理

热门文章

  1. android源码编译设置c++编译器,Android Stuido:使用CMake编译多个C/C++文件(1)
  2. 自动化测试框架cucumber_10分钟学会自动化测试框架--Cucumber + Watir
  3. BSN公网发展如何影响区块链的技术演进?
  4. android 记事簿源码,安卓记事本源代码,详细。
  5. 当安全遇上AI 阿里聚安全算法挑战赛 队伍经验分享
  6. 在网页中 生成QQ在线临时对话框/聊天
  7. 最优化方法及其实现(Optimization-Algorithm)C语言
  8. S32K144 Bootloader UDS 开发
  9. 消消乐php源码,手游泡泡消消乐设计(内附代码)
  10. 关于火绒安装,出现版本过低问题的解决办法