uC/OS-III的任务管理

uC/OS-III的任务管理

欢迎进入linuxweiyh的博客。。。

1.多任务管理就是在多个任务间调度和切换CPU使用权的过程。

2.任务的类型有两种:运行至完成型和无限循环型。
注:嵌入式系统一般使用的是无限循环类型的任务。在无限循环类型的任务中必须调用某个uC/OS-III服务函数,使该任务进入等待某个事件的状态。

3.任务的创建参考另一篇文章《uC/OS-III任务创建函数》

4.有关任务优先级的分配,这里说了一种方法:首先按照任务的关键性进行划分,分为关键任务和非关键任务。关键任务的优先级按照紧迫性来进行优先级的划分,而非关键任务可以遵照单调执行率调度发(RMS)进行划分,即执行率越高,优先级越高。

5.有关栈空间大小的确定,这里说的手动计算栈空间大小的方法很不现实,所以采用零一种方法,先分配很大的栈空间,然后,通过监视任务运行时栈的使用情况,就可以知道栈的实际使用空间。
这里摘抄自一段书上的原话,个人认为很重要:由于堆栈溢出很常见,并且会造成一些很奇怪的现象,因此,在开发和测试产品时,要一直监视任务在运行时的堆栈使用量。实际上,只要当有人提出她(或他)的应用程序的运行结果很奇怪时,首先就应该怀疑给任务分配的栈空间是不是太小了。
注:嵌入式系统的一个通用原则:不使用递归调用。

6.关于任务栈溢出检测,这里给出了一下几种方法。
(1)使用MMU(存储器管理单元)或MPU(存储器保护单元)
(2)使用具有堆栈溢出检测功能的CPU
(3)基于软件的堆栈溢出检测
(4)计算空闲堆栈空间的数量
注:以上4种方式,目前还未使用过其中任何一种。在uC/OS-III中提供了最后一种,具体的说明详见以后更新。

7.任务的用户态
从用户角度来看,任务的状态有5种,休眠态、就绪态、运行态、等待态、中断服务态。
(1)休眠态
书上有关休眠态的描述是任务已经存在于存储器中,但还不受uC/OS-III的管理。本人觉得这里的描述太啰嗦,所以给出最简单的描述,任务已经存在了,但是还没有添加到uC/OS-III任务表的任务表中。
当不再需要某一个任务时,用户可以调用OSTaskDel()把任务从任务就绪表中删除。
(2)就绪态
剩余的4种状态都可以进入到就绪态,uC/OS-III是通过任务就绪表记录就绪的任务。
(3)运行态
有关运行态的描述,有这么一句话,最重要的就绪任务进入运行态,这句话体现了uC/OS-III实时系统的最根本的调度依据–只有优先级最高的就绪任务才能获得CPU的使用权(对于单核CPU来说)。
当应用程序调用OSStart()时,或者当uC/OS-III调用OSIntExit或者OS_TASK_SW()时,uC/OS-III会切换到最重要的就绪任务,使其获得CPU的使用权。
(4)等待态
等待态的任务会被放入与所等待的事件相对应的等待表中。处于等待态的任务不消耗任何CPU的时间。
当任务等待的事件发生时,任务被重新放回到任务就绪表中,并且uC/OS-III会判断这个刚就绪的任务是否是最重要的任务。如果是,则当前正在运行任务的CPU使用权会被剥夺(放入任务就绪表),而刚就绪的任务会获得CPU的使用权。
注意:调用函数OSTaskSuspend()可无条件阻塞一个任务的运行,被阻塞的任务实际上并没有等待某个时间的发生。只有通过调用另外一个函数OSTaskResume(),才能使被阻塞的任务恢复运行。
(5)中断服务态
中断服务态其实就是发生中断时,当前正在运行的任务被挂起,CPU开始执行中断服务子程序ISR。ISR是任务等待的一种典型事件。
一般来说,ISR应当只是通知任务某个时间已经发生,而事件的处理则交个任务。ISR应当尽可能的短,中断处理的大部分工作应当在uC/OS-III可管理的任务级来做。ISR仅仅允许调用与Post相关的这一类函数(即OSFlagPost()、OSQPost()、OSSemPost()、OSTaskQPost()和OSTaskSemPost())。唯一一个不允许ISR调用的Post函数是OSMutexPost()。
中断能中断另外一个中断,这被称为中断嵌套。
注:状态转换图请参考《嵌入式实时操作系统uC/OS-III》P64。

8.任务在uC/OS-III内部的状态
在uC/OS-III内部,任务控制块OS_TCB中的成员TaskState记录任务的状态。uC/OS-III内部任务的状态总共有8种,延时、就绪、带超时检测的等待、等待、被挂起、延时且被挂起、带超时检测的等待且被挂起、等待且被挂起。
注意,在uC/OS-III内部并没有任务用户态中的运行态、休眠态和中断服务态,其中关于没有休眠态的原因很好理解,因为uC/OS-III内部不知道休眠态的任务的存在。而其他两种,目前本人也暂时还不理解。
注:详细的状态转换请参考《嵌入式实时操作系统uC/OS-III》P66。

9.任务控制块OS_TCB
任务控制块TCB是内核使用的一种数据接口,用来维护任务相关的信息。每个任务TCB。
uC/OS-III就是通过任务控制块TCB管理任务的。
下面是任务控制块TCB的源码,来自文件os.h的878行。

struct os_tcb {
    CPU_STK         *StkPtr;                           // 指针变量,指向任务当前的栈顶

    void            *ExtPtr;                           // 指向用户可定义的数据区,可以根据需要扩展TCB,其值由传递给OSTaskCreate()的参数p_ext设定

    CPU_STK         *StkLimitPtr;                      // 设置堆栈延伸的限制位置,有传递给OSTaskCreate()的参数stk_limit设定

                                                       // 在uC/OS-III内部,任务控制块TCB构成的是OS_TCB双向链表
    OS_TCB          *NextPtr;
    OS_TCB          *PrevPtr;

                                                       // 正在延时或在指定时间内等待事件的所有任务构成是双向的OS_TCB链表
    OS_TCB          *TickNextPtr;
    OS_TCB          *TickPrevPtr;

    OS_TICK_SPOKE   *TickSpokePtr;                     // 指向任务节拍轮的根条幅

    CPU_CHAR        *NamePtr;                          // 任务的名字

    CPU_STK         *StkBasePtr;                       // 任务堆栈的基地址,它的值永远是&???Stk[0]

    OS_TASK_PTR      TaskEntryAddr;                    // 任务代码的入口地址
    void            *TaskEntryArg;                     // 创建任务时传递个任务的参数的数值

    OS_PEND_DATA    *PendDataTblPtr;                   // 指向了一个表,该表包含了任务等待的所有事件对象的信息
    OS_STATE         PendOn;                           // 表示任务正在等待的事件的类型
    OS_STATUS        PendStatus;                       // 表示等待的结果

    OS_STATE         TaskState;                        // 任务的当前状态
    OS_PRIO          Prio;                             // 任务的当前优先级
    CPU_STK_SIZE     StkSize;                          // 任务堆栈的大小
    OS_OPT           Opt;                              // 任务创建时传递给OSTaskCreate()的可选参数options的数值

    OS_OBJ_QTY       PendDataTblEntries;               // 表示任务同时等待的事件对象的数目,与.PendDataTblPtr配合使用

    CPU_TS           TS;                               // 存储事件发生时的时间戳

    OS_SEM_CTR       SemCtr;                           // 任务內建信号量的计数器

    // 与任务等待延时有关
    OS_TICK          TickCtrPrev;
    OS_TICK          TickCtrMatch;
    OS_TICK          TickRemain;

    // 与时间片的分配相关
    OS_TICK          TimeQuanta;
    OS_TICK          TimeQuantaCtr;

#if OS_MSG_EN > 0u
    void            *MsgPtr;                           // 指向接收到的消息
    OS_MSG_SIZE      MsgSize;                          // 消息的长度
#endif

#if OS_CFG_TASK_Q_EN > 0u
    OS_MSG_Q         MsgQ;                             // 任务內建消息队列
#if OS_CFG_TASK_PROFILE_EN > 0u
    CPU_TS           MsgQPendTime;                     // 一条消息到达所花费的时间
    CPU_TS           MsgQPendTimeMax;                  // 一条消息到达所花费的最长时间
#endif
#endif

#if OS_CFG_TASK_REG_TBL_SIZE > 0u
    OS_REG           RegTbl[OS_CFG_TASK_REG_TBL_SIZE];  // 任务寄存器,用来存储任务专用的信息
#endif

#if OS_CFG_FLAG_EN > 0u
    OS_FLAGS         FlagsPend;                         // 包含任务等待的那些事件的标志位
    OS_FLAGS         FlagsRdy;                          // 记录任务在等待的事件标志中有哪些已经就绪
    OS_OPT           FlagsOpt;                          // 等待的类型
#endif

#if OS_CFG_TASK_SUSPEND_EN > 0u
    OS_NESTING_CTR   SuspendCtr;                        // 记录任务被挂起的次数,与OSTaskSuspend()和OSTaskResume()的使用相关
#endif

#if OS_CFG_TASK_PROFILE_EN > 0u
    OS_CPU_USAGE     CPUUsage;                         // 表示任务的CPU利用率
    OS_CTX_SW_CTR    CtxSwCtr;                         // 记录任务执行的频繁程度
    CPU_TS           CyclesDelta;                      // 记录任务一次运行期间占用CPU的时间
    CPU_TS           CyclesStart;                      // 表示任务每次开始运行时的时间戳
    OS_CYCLES        CyclesTotal;                      // 表示任务总的执行时间
    OS_CYCLES        CyclesTotalPrev;                  // 表示任务前一次总的执行时间

    CPU_TS           SemPendTime;                      // 信号量的发送所花费的时间
    CPU_TS           SemPendTimeMax;                   // 信号量发送到一个任务所花费的最长时间
#endif

#if OS_CFG_STAT_TASK_STK_CHK_EN > 0u
    CPU_STK_SIZE     StkUsed;                          // 已使用的栈空间大小
    CPU_STK_SIZE     StkFree;                          // 未使用的栈空间大小
#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN
    CPU_TS           IntDisTimeMax;                    // 任务的最大中断关闭时间
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
    CPU_TS           SchedLockTimeMax;                 // 记录任务给调度器上锁的时间
#endif

// 与调试相关
#if OS_CFG_DBG_EN > 0u
    OS_TCB          *DbgPrevPtr;
    OS_TCB          *DbgNextPtr;
    CPU_CHAR        *DbgNamePtr;
#endif
};

任务控制块OS_TCB中成员的分类总结:
任务本身有关的成员:NamePtr、TaskState、Prio、TaskEntryAddr、TaskEntryArg、ExtPtr
任务栈有关的成员:StkPtr、StkLimitPtr、StkBasePtr、StkSize
任务链表有关的成员:
任务延时有关的成员:
时间片有关的成员:
內建信号量有关的成员:
內建消息队列有关的成员:
事件有关的成员:
事件标志组有关的成员:
注:有关以上部分的总结当用到的时候再填充。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值