4.空闲任务与钩子函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_38245860/article/details/80689438

CPU使用率的计算,先去统计CPU的空闲率,100%-空闲率=CPU使用率。  

临界区的概念:临界区有进入和退出操作,在进入临界区和退出临界区这段时间内执行的代码是独享CPU使用权的!  

rt_enter_critical(); //进入临界区
tick = rt_tick_get();
while (rt_tick_get() - tick < 10)
{
    total_count ++;
    loop = 0;
    while (loop < 100) loop ++;
 }
rt_exit_critical();//退出临界区

计算原理:这段在临界区内执行的代码在10个系统滴答时间内让total_count自加,这里的loop是一个循环,loop加100次,total_count才加一次,作用是让CPU完全发挥作用,这里是计算了完全使用CPU时,total_count能自加多少个。

然后是系统不进入临界区来执行这段代码,因为这段代码放在空闲任务中,只有其他任务执行完之后才会运行空闲任务(count++),得到的是count。

count/total_count就是CPU的空闲率,用100%减去空闲率就是使用率。

/*
 * 程序清单:空闲任务钩子例程
 *
 * 这个例程设置了一个空闲任务钩子用于计算CPU使用率,并创建一个线程循环打印CPU使用率
 * 通过修改CPU使用率打印线程中的休眠tick时间可以看到不同的CPU使用率
 */

#include <rtthread.h>
#include <rthw.h>

#define THREAD_PRIORITY      25
#define THREAD_STACK_SIZE    512
#define THREAD_TIMESLICE     5

/* 指向线程控制块的指针 */
static rt_thread_t tid = RT_NULL;

#define CPU_USAGE_CALC_TICK    10
#define CPU_USAGE_LOOP        100

static rt_uint8_t  cpu_usage_major = 0, cpu_usage_minor = 0;

/* 记录CPU使用率为0时的总count数 */
static rt_uint32_t total_count = 0;

/* 空闲任务钩子函数 */
static void cpu_usage_idle_hook()
{
    rt_tick_t tick;
    rt_uint32_t count;
    volatile rt_uint32_t loop;

    if (total_count == 0)
    {
        /* 获取 total_count */
        rt_enter_critical();
        tick = rt_tick_get();
        while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK)
        {
            total_count ++;
            loop = 0;
            while (loop < CPU_USAGE_LOOP) loop ++;
        }
        rt_exit_critical();
    }

    count = 0;
    /* 计算CPU使用率 */
    tick = rt_tick_get();
    while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK)
    {
        count ++;
        loop  = 0;
        while (loop < CPU_USAGE_LOOP) loop ++;
    }

    /* 计算整数百分比整数部分和小数部分 */
    if (count < total_count)
    {
        count = total_count - count;
        cpu_usage_major = (count * 100) / total_count;
        cpu_usage_minor = ((count * 100) % total_count) * 100 / total_count;
    }
    else
    {
        total_count = count;

        /* CPU使用率为0 */
        cpu_usage_major = 0;
        cpu_usage_minor = 0;
    }
}

void cpu_usage_get(rt_uint8_t *major, rt_uint8_t *minor)
{
    RT_ASSERT(major != RT_NULL);
    RT_ASSERT(minor != RT_NULL);

    *major = cpu_usage_major;
    *minor = cpu_usage_minor;
}

/* CPU使用率打印线程入口 */
static void thread_entry(void *parameter)
{
    rt_uint8_t major, minor;

    while (1)
    {
        cpu_usage_get(&major, &minor);
        rt_kprintf("cpu usage: %d.%d%\n", major, minor);

        /* 休眠50个OS Tick */
        /* 手动修改此处休眠 tick 时间,可以模拟实现不同的CPU使用率 */
        rt_thread_delay(50);
    }
}

int cpu_usage_init()
{
    /* 设置空闲线程钩子 */
    rt_thread_idle_sethook(cpu_usage_idle_hook);

    /* 创建线程 */
    tid = rt_thread_create("thread",
                           thread_entry, RT_NULL, /* 线程入口是thread_entry, 入口参数是RT_NULL */
                           THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
    if (tid != RT_NULL)
        rt_thread_startup(tid);
    return 0;
}
/* 如果设置了RT_SAMPLES_AUTORUN,则加入到初始化线程中自动运行 */
#if defined (RT_SAMPLES_AUTORUN) && defined(RT_USING_COMPONENTS_INIT)
    INIT_APP_EXPORT(cpu_usage_init);
#endif
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(cpu_usage_init, idle hook sample);

猜你喜欢

转载自blog.csdn.net/sinat_38245860/article/details/80689438