在VxWorks平台如何计算cpu的利用率 .

本文详细介绍了在VxWorks环境下监测CPU利用率的方法,包括利用spyLib库的spy工具实现抽样技术监测,以及通过特殊任务消耗空闲时间以估算整体CPU使用率。文章还提供了实现代码及分析过程,旨在提升对嵌入式系统性能监控的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 最近我在学VxWorks,但是总觉得如果不做点什么,光看那E版的联机文档,不会给我的功力带来突飞猛进。我想起前一阵子,在给我们公司的产品加OAM功能时,需要测量CPU的利用率,我们公司的VxWorks大虾们利用了反汇编攻克,应该算是成功了,但是不太稳定,偶尔回抛出异常。于是我决心向困难挑战。

 

经过查阅资料,浏览各大嵌入式开发论坛,总结得下面一些方法,各有利弊。首先我先介绍一下VxWorks的spyLib库提供的spy工具的实现原理。

 

Spy利用辅助定时器来产生中断,并且为每个任务维护一个计数器。然后记下被中断的任务,并且将该任务的计数器加一。经过一段时间后,每个任务的计数器反映了该任务占用CPU利用率的情况。很明显,这是利用抽样技术。并且得到的cpu利用率的准确程度取决于任务的持续性和周期性。

 

通过查找spyLib.h的文件,我们发现除了spy()函数外,还有一spyCommon函数,带一函数指针参数。推测函数指针类型为(int)(*p)(char * fmtStr,…)(经过验证确实如此)。所以可以写一自己的函数去接受spy需要打印的数据,Spy调用该函数按行打印结果。我们可以不断分析一行字符串来得到我们需要的结果。

int SpyPtnFunc(const char * fmtPtn,...)

{

 

  char buf[128];

  CPUUSAGEDATAMSG data;

 

  va_list vl;

  va_start(vl,fmtPtn);

  vsprintf(buf,fmtPtn,vl);  //得到一行字符串。

  va_end(vl);

 

  //分析buf,得到一个任务的Cpu的使用情况。

  return 0;

}

 

另外一种方法是利用一特殊任务,该任务的优先级比系统中的所有任务的优先级都低,该任务是死循环,该任务的目的就是消耗cpu资源,占用cpu空闲时间,因为当系统中其它任务都被挂其时,该任务才能得到cpu的使用权。假设一段时间total内,该任务的运行时间为idle,cpu利用率的计算公式为(total-idle)%total。这一种方法实现起来很简单,但是它只能算得整个系统的cpu使用情况,不能得到单个任务的cpu使用情况!同时它会使cpu满负荷工作。源代码如下

#include "VxWorks.h"

#include "semLib.h"

#include "taskLib.h"

 

#define SECONDS_TO_BURN 60

typedef struct cpuUsage {

    SEM_ID        startSem;

    int           didNotComplete;

    unsigned long ticksNoContention;

    int           nBurnNoContention;

    unsigned long ticksNow;

    int           nBurnNow;

    double        usage;

} cpuUsage;

 

static cpuUsage *pcpuUsage=0;

 

static double cpuBurn()

{

    int i;

    double result = 0.0;

 

    for(i=0;i<5; i++) result += sqrt((double)i);

    return(result);

}

 

static void cpuUsageTask()

{

    while(TRUE) {

        int    i;

        unsigned long tickStart,tickEnd;

 

        semTake(pcpuUsage->startSem,WAIT_FOREVER);

        pcpuUsage->ticksNow=0;

        pcpuUsage->nBurnNow=0;

tickStart = tickGet();

 

        for(i=0; i< pcpuUsage->nBurnNoContention; i++) {

            cpuBurn();

            pcpuUsage->ticksNow = tickGet() - tickStart;

            ++pcpuUsage->nBurnNow;

        }

        tickEnd = tickGet();

        pcpuUsage->didNotComplete = FALSE;

        pcpuUsage->ticksNow = tickEnd - tickStart;

    }

}

 

 double getCpu()

{

    if(pcpuUsage->didNotComplete && pcpuUsage->nBurnNow==0) {

        pcpuUsage->usage = 0.0;

    } else {

        double temp;

        double ticksNow,nBurnNow;

 

        ticksNow = (double)pcpuUsage->ticksNow;

        nBurnNow = (double)pcpuUsage->nBurnNow;

        ticksNow *= (double)pcpuUsage->nBurnNoContention/nBurnNow;

        temp = ticksNow - (double)pcpuUsage->ticksNoContention;

        temp = 100.0 * temp/ticksNow;

        if(temp<0.0 || temp>100.0) temp=0.0; /*handle tick overflow*/

        pcpuUsage->usage = temp;

}

 

    pcpuUsage->didNotComplete = TRUE;

    semGive(pcpuUsage->startSem);

    printf("CPU usage:%f/r/n",pcpuUsage->usage);

    return(pcpuUsage->usage);

}

 

 void cpuUsageInit(void)

{

    unsigned long tickStart,tickNow;

    int           nBurnNoContention=0;

    int         ticksToWait;

 

    ticksToWait = SECONDS_TO_BURN*sysClkRateGet();

    pcpuUsage = calloc(1,sizeof(cpuUsage));

    tickStart = tickGet();

    /*wait for a tick*/

    while(tickStart==(tickNow = tickGet())) {;}

    tickStart = tickNow;

    while(TRUE) {

        if((tickGet() - tickStart)>=ticksToWait) break;

        cpuBurn();

        nBurnNoContention++;

    }

    pcpuUsage->nBurnNoContention = nBurnNoContention;

    pcpuUsage->startSem = semBCreate (SEM_Q_FIFO,SEM_EMPTY);

    pcpuUsage->ticksNoContention = ticksToWait;

    pcpuUsage->didNotComplete = TRUE;

    taskSpawn("cpuUsageTask",255,VX_FP_TASK,1000,(FUNCPTR)cpuUsageTask,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

}

 

以上两种方法我都实现了,工作的很正常!

1 TORNADO的调试工具 4 1.1 WINDSHELL 4 1.1.1 简介 4 1.1.2 功能键 5 1.1.3 特殊控制符 6 1.1.4 计算功能 6 1.1.5 环境变量 6 1.1.6 内置指令 6 1.2 BROWSE 17 1.2.1 内存查看 17 1.2.2 模块信息 17 1.2.3 堆栈使用率 18 1.2.4 CPU占有率 18 1.2.5 任务信息 19 1.2.6 中断向量表 19 1.2.7 实体查看 20 1.3 DEBUGGER 21 1.3.1 条件断点 21 1.3.2 代码显示 21 1.4 TARGET SERVER 21 1.4.1 使用串口调试 21 1.4.2 重定向 21 1.5 WINDVIEW 22 1.5.1 记录层次 22 1.5.2 记录数据存储方式 22 1.5.3 传送方式 22 1.5.4 数据分析 23 1.6 TRIGGER 23 1.7 TELNET 24 1.8 调试模式 24 1.8.1 任务调试模式下的多任务调试 26 1.8.2 系统调试模式下多任务的调试: 27 1.8.3 中断服务程序的调试 28 2 V2支撑的调试手段 28 2.1 各模块提供的函数 28 2.2 如何查看ERROR.LOG文件 29 2.2.1 定位到具体的出错行 31 3 V3支撑的调试手段 31 1.1. 进程调试 31 1.2. 查看所有进程信息:OSS_DBGGETALLUSEPCBINFO 31 1.3. 查看当前运行的进程信息 31 1.3.1. 进程断点设置:b 31 1.3.2. 当前进程运行信息:OSS_DbgGetCurPCBInfo 32 1.3.3. 当前进程的消息信息:OSS_DbgGetCurMsgInfo 32 1.3.4. 进程断点取消:bd 32 1.3.5. 恢复进程运行:tr 32 1.4. 内存观察 32 1.4.1. 消息队列堆积、阻塞观察:tw 32 1.4.2. 任务消息队列观察:OSS_DbgShowQueueCtl 33 1.4.3. 任务UB使用观察:OSS_DbgShowTaskUB 33 1.4.4. 进程使用UB情况:OSS_DbgShowProcUBInfo 34 1.4.5. UB的配置和当前状态:OSS_DbgMemUbUsePrn/ OSS_DbgShowUbPool 34 1.5. 通信和定时器状态观察 35 1.5.1. 通信状态显示OSS_DbgShowComm 35 1.5.2. 测试板间通信是否正常:OSS_DbgRudpPing 35 1.5.3. 单板上定时器的使用信息:OSS_DbgGetTimerInfo 36 1.5.4. 单板进程使用定时器的信息:OSS_DbgGetTimerInfoOfProc 36 1.6. 杂项观察 36 1.6.1. 异常发生后信息观察:OSS_DbgShowExcInfo 36 1.6.2. 堆栈使用率/运行时间统计:zte 36 1.6.3. 进程最近打印内容观察:ztecall/ ztemsg 36 1.6.4. 进程最近打印的1K内容和打印时间:zteprint 37
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值