前几天,有小伙伴问了大概这么一个问题:RTOS有很多任务,如果没有执行任务了,都在延时等待(如vTaskDelay),或等待事件触发(如xQueueReceive),CPU在干嘛?
从裸机转向RTOS的小伙伴,不知道你有没有过这样的疑问?
裸机 vs 系统
裸机情况下,就是一个while死循环:
int main(void)
{
/* 初始化 */
while(1)
{
/* 循环处理多项事情 */
}
}
换上RTOS就是为了提高CPU利用率,使其执行多个任务(多个while):
void Task1(void)
{
/* 初始化 */
while(1)
{
/* 处理事情1 */
}
}
void Task2(void)
{
/* 初始化 */
while(1)
{
/* 处理事情2 */
}
}
void Task3(void)
void Task4(void)
......
通过对比裸机和操作系统的区别,再结合开篇的问题,你能联想到什么?
裸机情况下,CPU永远都在while(1)大循环中。那么,在操作系统下,CPU除了执行任务中的while,其他时间都执行到哪儿去了?
答案是:CPU在执行操作系统自带的空闲任务/线程/进程。
OS空闲任务
我们打开Windows系统的任务管理器,不操作电脑时,你会发现一个进程CPU占有率很高:
没错,这个进行就是系统空闲进程。
在RTOS实时操作系统中,也有一个类似这样的线程(任务),叫空闲任务。
- uCOS中空闲任务叫:OS_TaskIdle
- FreeRTOS中空闲任务叫:prvIdleTask
当然你在线调试带有RTOS操作系统的项目时,暂停运行代码,有很大概率CPU会执行到空闲任务。
比如uCOS空闲函数:
void OS_TaskIdle (void *p_arg)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */
for (;;) {
OS_ENTER_CRITICAL();
OSIdleCtr++;
OS_EXIT_CRITICAL();
OSTaskIdleHook(); /* Call user definable HOOK */ }
}
其实,你会发现这个系统空闲函数也没什么代码,就是在哪儿“死循环”。
这里有一个 OSTaskIdleHook();函数是提供给用户的,默认情况下,这个函数也是啥东西没有,需要用户根据自己情况添加代码。这里可以参看我之前分享的文章:RTOS中钩子函数HOOK的用途及用法。
所以,回到本文的问题:RTOS没有执行任务,CPU在干嘛?
答案是:默认情况下,啥都没干!
当然,如果你看到CPU太闲了,你也可以让它干点事。比如在上面的 OSTaskIdleHook() 函数里面添加一句打印输出:
printf("CPU在偷懒了...\n\r");
最后,你对RTOS实时操作系统内核了解多少?有多少小伙伴阅读过内核源码?
END
作者: strongerHuang
来源:strongerHuang
推荐阅读
欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。