CPU的利用率是怎么计算的

分类:

方法1: 使用CPU的处理能力基准计算实时CPU占用率 
具体描述: 
(1) 在RTOS系统启动前, 使用Tick中断测试CPU的处理能力基准 CPUPerformanceBase; 
(2) 在系统进入运行后, 使用空闲任务执行与测试CPU处理能力基准完全相同的算法, 得到RTCPUPerformance. 
(3) 周期地计算CPU占用率, 并清除RTCPUPerformance的值, 一般每秒钟计算一次: 
RealTime CPU Load = 1 - (RTCPUPerformance/CPUPerformanceBase) * 100% 

优点: 
(1) 实现简单 
(2) 所得到的CPU占用率非常准确, 误差只取决于CPUPerformanceBase的测试结果和整除时的余数, 通常误差小于1% 
(3) 不占用硬件资源 

缺点: 
(1) CPU必须一直全速运行, 不能修改CPU主频, 也不能使CPU进入掉电保护模式 
(2) 不能得到系统中每个任务对CPU占用率的贡献 
(3) 必须有一个空闲任务才能计算 

评价: 
这个算法只适用于工控, 电信等对不需要使CPU进入掉电保护模式的领域. 

方法2: 在Tick中断中对RTOS中的任务进行采样 
具体描述: 
(1) 系统进入运行后, 每次Tick中断发生时, 采样一下当前正在执行的任务, 如果CPU处于HALT态, 累加haltTimes 
(2) 周期性地计算CPU占用率, 一般每秒钟计算一次, 并清除haltTimes:(tickIntFrequance表示Tick中断的发生频率) 

RealTime CPU Load = haltTimes / tickIntFrequance 

某个任务对CPU占用率的贡献 = 一个周期内该任务被采样到的次数 / tickIntFrequance * 100% 

优点: 
(1) 实现简单 
(2) 支持CPU掉电模式 
(3) 可以大致得到每个任务对CPU占用率的贡献 

缺点: 
(1) 误差取决于Tick的频率和OS中每个任务的运行时长, 因此误差非常大 

评价: 
这个算法适用于对CPU占用率精度要求不高的消息电子产品. 

方法3: 精确计算每个任务对CPU占用率的贡献 
具体描述: 
(1) 除Tick中断外,另开一个比Tick中断频率快若干倍的周期中断(就叫AUXTimer中断吧), 这个中断只对一个计数器执行一次累加. 
(2) 在OS每次执行任务切换时读取该计数器的值(AUXTimer), 并保存到TCB中, 比如, 从任务Task1切换到任务Task2, 算法如下: 

Task1, 换出动作: 
task1的结束运行时间 = AUXTimer的当前值 
task1的总运行时间 = task1的总运行时间 + task1的结束运行时间 - task1的开始运行时间 

Task2, 换入动作: 
task2的开始运行时间 = AUXTimer的当前值 

(以上算法中没有考虑数字回绕, 在工程实现时应当考虑, 发生回绕后任务的结束运行时间小于任务的开始运行时间. 

(3) 周期性地计算CPU占用率, 一般每秒钟计算一次, 并清除每个任务的总运行时间, 下面的公式中, 一个周期内的总时间等于AUXTimer周期除以Tick周期得到的倍数: 

某个任务对CPU占用率的贡献 = 一个周期内该任务的总运行时间 / 一个周期内的总时间 

RealTime CPU Load = 所有任务的CPU占用率之和 

对这个方法进行简单改进, 就可以实现对CPU占用率进行实时测量, 看官自己动动脑筋吧. 

优点: 
(1) 误差取决于AUXTimer中断的频率, 可以非常精确地得到每个任务对CPU占用率的贡献 

缺点: 
(1) 复杂, 加大了任务切换时的开销 

(2) 和前两种算法相比, 这个算法要多占用一个硬件资源



转摘:http://blog.chinaunix.net/uid-21067667-id-447556.html


Vxworks CPU利用率计算:

利用一特殊任务,该任务的优先级比系统中的所有任务的优先级都低,该任务是死循环,该任务的目的就是消耗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);

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值