ucos 统计任务 OS_TaskStat()

在百度里看到张连聘文章,对ucos的两个系统任务分析的很恰当,就是最后边一段观点我不太认同,在此非常感谢张连聘。

先把ucosii中的原文写在这,然后再说一下我的具体理解(下面有我的理解部分)。

我觉得这篇文章对ucos的两个系统任务分析的很恰当,就是最后边一段观点我不太认同,在此非常感谢张连聘。

先把ucosii中的原文写在这,然后再说一下我的具体理解。

μC/OS-Ⅱ有一个提供运行时间统计的任务。这个任务叫做OS_TaskStat(),如果用户将系统定义常数OS_TASK_STAT_EN(见文件OS_CFG.H)设为1,这个任务就会建立。一旦得到了允许,OS_TaskStat()每秒钟运行一次(见文件OS_CORE.C),计算当前的CPU利用率。换句话说,OS_TaskStat()告诉用户应用程序使用了多少CPU时间,用百分比表示,这个值放在一个有符号8位整数OSCPUsage中,精读度是1个百分点。

如果用户应用程序打算使用统计任务,用户必须在初始化时建立一个唯一的任务,在这个任务中调用OSStatInit()。换句话说,在调用系统启动函数OSStart()之前,用户初始代码必须先建立一个任务,在这个任务中调用系统统计初始化函数OSStatInit(),然后再建立应用程序中的其它任务。程序清单L3.12是统计任务的示意性代码。

程序清单 L3.12 初始化统计任务.

Void main (void)

{

OSInit();

OSStart();

}

Void TaskStart (void *pdata)

{

OSStatInit();

for (;;) {

}

}

因为用户的应用程序必须先建立一个起始任务[TaskStart()],当主程序main()调用系统启动函数OSInit()的时候,μC/OS-Ⅱ只有3个要管理的任务:TaskStart()、OSTaskIdle()和OS_TaskStat()。请注意,任务TaskStart()的名称是无所谓的,叫什么名字都可以。因为μC/OS-Ⅱ已经将空闲任务的优先级设为最低,即OS_LOWEST_PR10,统计任务的优先级设为次低,OS_LOWEST_PR10减1。启动任务TaskStart()总是优先级最高的任务。

图F3.4解释初始化统计任务时的流程。用户必须首先调用的是μC/OS-Ⅱ中的系统初始化函数OSInit(),该函数初始化μC/OS-Ⅱ[图F3.4(2)]。有的处理器(例如Motorola的MC68HC11),不需要“设置”中断向量,中断向量已经在ROM中有了。用户必须调用OSTaskCreat()或者OSTaskCreatExt()以建立TaskStart()[图F3.4(3)]。进入多任务的条件准备好了以后,调用系统启动函数OSStart()。这个函数将使TaskStart()开始执行,因为TaskStart()是优先级最高的任务[图F3.4(4)]]。

TaskStart()负责初始化和启动时钟节拍[图F3.4(5)]。在这里启动时钟节拍是必要的,因为用户不会希望在多任务还没有开始时就接收到时钟节拍中断。接下去TaskStart()调用统计初始化函数OSStatInit()[图F3.4(6)]。统计初始化函数OSStatInit()决定在没有其它应用任务运行时,空闲计数器(OSIdleCtr)的计数有多快。奔腾II微处理器以333MHz运行时,加1操作可以使该计数器的值达到每秒15,000,000次。OSIdleCtr的值离32位计数器的溢出极限值4,294,967,296还差得远。微处理器越来越快,用户要注意这里可能会是将来的一个潜在问题。

系统统计初始化任务函数OSStatInit()调用延迟函数OSTimeDly()将自身延时2个时钟节拍以停止自身的运行[图F3.4(7)]。这是为了使OSStatInit()与时钟节拍同步。μC/OS-Ⅱ然后选下一个优先级最高的进入就绪态的任务运行,这恰好是统计任务OSTaskStat()。读者会在后面读到OSTaskStat()的代码,但粗看一下,OSTaskStat()所要做的第一件事就是查看统计任务就绪标志是否为“假”,如果是的话,也要延时两个时钟节拍[图F3.4(8)]。一定会是这样,因为标志OSStatRdy已被OSInit()函数初始化为“假”,所以实际上DSTaskStat也将自己推入休眠态(Sleep)两个时钟节拍[图F3.4(9)]。于是任务切换到空闲任务,OSTaskIdle()开始运行,这是唯一一个就绪态任务了。CPU处在空闲任务OSTaskIdle中,直到TaskStart()的延迟两个时钟节拍完成[图3.4(10)]。两个时钟节拍之后,TaskStart()恢复运行[图F3.4(11)]。 在执行OSStartInit()时,空闲计数器OSIdleCtr被清零[图F3.4(12)]。然后,OSStatInit()将自身延时整整一秒[图F3.4(13)]。因为没有其它进入就绪态的任务,OSTaskIdle()又获得了CPU的控制权[图F3.4(14)]。一秒钟以后,TaskStart()继续运行,还是在OSStatInit()中,空闲计数器将1秒钟内计数的值存入空闲计数器最大值OSIdleCtrMax中[图F3.4(15)]。

OSStarInit()将统计任务就绪标志OSStatRdy设为“真”[图F3.4(16)],以此来允许两个时钟节拍以后OSTaskStat()开始计算CPU的利用率。

统计任务的初始化函数OSStatInit()的代码如程序清单 L3.13所示。

程序清单 L3.13 统计任务的初始化.

void OSStatInit (void)

{

OSTimeDly(2);

OS_ENTER_CRITICAL();

OSIdleCtr = 0L;

OS_EXIT_CRITICAL();

OSTimeDly(OS_TICKS_PER_SEC);

OS_ENTER_CRITICAL();

OSIdleCtrMax = OSIdleCtr;

OSStatRdy = TRUE;

OS_EXIT_CRITICAL();

}

统计任务OSStat()的代码程序清单L3.14所示。在前面一段中,已经讨论了为什么要等待统计任务就绪标志OSStatRdy[L3.14(1)]。这个任务每秒执行一次,以确定所有应用程序中的任务消耗了多少CPU时间。当用户的应用程序代码加入以后,运行空闲任务的CPU时间就少了,OSIdleCtr就不会像原来什么任务都不运行时有那么多计数。要知道,OSIdleCtr的最大计数值是OSStatInit()在初始化时保存在计数器最大值OSIdleCtrMax中的。CPU利用率(表达式[3.1])是保存在变量OSCPUsage[L3.14(2)]中的:

[3.1]表达式Need to typeset the equation.

一旦上述计算完成,OSTaskStat()调用任务统计外界接入函数OSTaskStatHook() [L3.14(3)],这是一个用户可定义的函数,这个函数能使统计任务得到扩展。这样,用户可以计算并显示所有任务总的执行时间,每个任务执行时间的百分比以及其它信息(参见1.09节例3)。

程序清单 L3.14 统计任务

void OSTaskStat (void *pdata)

{

INT32U run;

INT8S usage;

pdata = pdata;

while (OSStatRdy == FALSE) { (1)

OSTimeDly(2 * OS_TICKS_PER_SEC);

}

for (;;) {

OS_ENTER_CRITICAL();

OSIdleCtrRun = OSIdleCtr;

run = OSIdleCtr;

OSIdleCtr = 0L;

OS_EXIT_CRITICAL();

if (OSIdleCtrMax > 0L) {

usage = (INT8S)(100L - 100L * run / OSIdleCtrMax); (2)

if (usage > 100) {

OSCPUUsage = 100;

} else if (usage < 0) {

OSCPUUsage = 0;

} else {

OSCPUUsage = usage;

}

} else {

OSCPUUsage = 0;

}

OSTaskStatHook(); (3)

OSTimeDly(OS_TICKS_PER_SEC);

}

}

还是先仔细看看源码,这样有利于你搞明白统计任务的实现原理和应用方法。

下面我说一下我个人的理解:

统计任务的实现原理大致上是这样的,一开始统计任务要初始化,主要是保证μC/OS-Ⅱ的空闲任务准时运行1s的时间。我们看看这个任务都干些什么。

void OSTaskIdle (void *pdata)

{

pdata = pdata;

for (;;) {

OS_ENTER_CRITICAL();

OSIdleCtr++;

OS_EXIT_CRITICAL();

}

}

这个任务其实就是给一个OSIdleCtr这个变量加一。这样在保证空闲任务运行1s的时间内,就把1s内空闲任务中OSIdleCtr变量达到此次开机的最大值。而且在初始化统计任务中把这个变量的值赋给了OSIdleCtrMax 这个变量。如果不重启的话,这个值是不变的。用这个值来算以后有了其他任务时cpu的利用率。具体怎么实现的计算和怎么实现的一开始让空闲任务运行1s的。可以看上面的源码。其中,我用红色字体标出的,我认为应该是2分钟。看源码就会知道。

至于,启动多任务之后,统计任务如何计算cpu利用率的,关于书上说的统计任务每秒执行一次的问题,我认为这种说法不对,统计任务并不是每秒运行一次,大家可以想一想,统计任务执行到最后时是OSTimeDly(OS_TICKS_PER_SEC);这样一个函数。表示延迟一分钟。而只有统计任务延时时空闲任务才有可能运行,所以每当统计任务运行时OSIdleCtr的值都是在可能的1s内记的数。因为在统计任务在赋完值之后清零了。所以说,统计任务不是1s运行一次,只不过统计任务运行时用到的变量都是在1s内的数据。所以,用统计任务可以统计cpu利用率。

相关文章

  1. 嵌入式系统开发的基础是什么

    1.硬件基础,皮毛就可以,实在不会就算了,反正公司有硬件工程师,而且还可以找供货商要技术支持,如果要软硬件都通,那模电数电都是基础啊,跑不掉的: 2.C/C++/C#/JAVA选一种,推荐C,汇编很少用没太大必要: 3.操作系统,linux/wince/ucos/android等任选一种,初学推荐u ...

  2. DSP编程的一些经验

    我看过一个故事:在20世纪30年代,英国送奶公司送到订户门口的牛奶,没有盖子也没封口,麻雀和红襟鸟可以很容易的喝到上层的奶皮.后来,牛奶公司把瓶口用锡箔纸封装起来,想防止鸟的偷食.但20年后,英国的麻雀都学会了用嘴把奶瓶的锡箔纸啄开,继续偷吃它们喜欢的奶皮.然而,同样是20年,红襟鸟却一直没学会这种 ...

  3. 嵌入式开发工程师需要具备哪些能力?

    近年来,随着嵌入式技术在整个信息产业的广泛应用和高速发展,嵌入式技术也正在迅速改变着我们的生活方式和工作方式.更重要的是智能化嵌入式产品的广泛应用已经在其中扮演着不可替代的角色.例如我们身边常见的手 机.iPad.机顶盒.智能家居等都是嵌入式产品,IT行业的发展也势不可挡地进入了嵌入式时代,同时也对 ...

  4. ARM工控主板选型指南

    对于工业控制的朋友们来说,每一个项目的实现都是一个非常艰苦的过程,特别是工控主板的选择和程序代码的调试. 由于ARM有比INTEL处理器更多的工控特性优势,比如低功耗.高效率.嵌入性能强.可移植实时操作系统等,渐渐成为工控领域主控单元的首选. 工具/原料 Cortex-M Cortex-A 方法/步 ...

  5. 使用GNUPLOT设计一顶漂亮的草帽

    gnuplot画图程序可以用来实物外形设计,用它画出来的图形美观大方,非常接近实物,所以很多建筑工程的效果图用它来画也比较逼真.今天,小编教你如何利用gnuplot设计一顶漂亮的草帽. 工具/原料 gnuplot 方法/步骤 先看第一个草帽模型--圆锥形草帽.圆锥曲面的函数表达式可以用参数方程表示, ...

  6. 用Excel数据透视表 统计日期 显示日期

    用Excel做任务管理时,如何通过数据透视表显示任务开始和结束时间,非常然人头疼,这里教你如何在数据透视表中显示日期.在做任务管理或时间分析时,这是非常有用的哦? 关键点是:利用Excel的数据透视表中,统计数据的显示格式来显示日期 工具/原料 Excel 方法/步骤 确定分析内容: 我们这里要做统 ...

  7. 用EXCEL制作个人工作总结模板:[2]自动统计

    在本系列经验<用EXCEL制作个人工作总结一模板>中已经说过如何制作一个工作总结模板了,正如前文所说,工作中经常需要写工作总结,尤其是IT等相关行业,甚至每天都要写总结进行汇报工作,尤其设计工时的计算,每一项工作可能时间跨度是几天到几十天,但是这项工作究竟有多少工作量呢?一般需要计算工时 ...

  8. 嵌入式软件学习课程包括哪些?

    在嵌入式软件方面最重要的课程包括: (1) 嵌入式微处理器结构与应用:这是一门嵌入式硬件基础课程,我们说过,嵌入式是软硬件结合的技术,搞嵌入式软件的人应对ARM处理器工作原理和接口技术有充分了解,包括ARM的汇编指令系统.若不了解处理器原理,怎么能控制硬件工作,怎么能写出节省内存又运行高速的最优代码 ...

  9. 统计报表系统FineReport中如何创建上报任务

    上报任务管理是指在上报流程的基础上创建一个上报任务,那么此时系统中就实实在在的存在一个上报流程需要流转,可以将上报任务当做是上报流程的一个实例,而在我的上报任务节点下面就会出现一个上报任务.下面就通过统计报表系统FineReport来介绍一下如何创建上报任务. 工具/原料 统计报表系统FineRep ...