微信公眾號(hào) | strongerHuang
前幾天,有小伙伴問了大概這么一個(gè)問題:RTOS有很多任務(wù),如果沒有執(zhí)行任務(wù)了,都在延時(shí)等待(如vTaskDelay),或等待事件觸發(fā)(如xQueueReceive),CPU在干嘛?
從裸機(jī)轉(zhuǎn)向RTOS的小伙伴,不知道你有沒有過這樣的疑問?
裸機(jī) vs 系統(tǒng)
裸機(jī)情況下,就是一個(gè)while死循環(huán):
int main(void)
{
/* 初始化 */
while(1)
{
/* 循環(huán)處理多項(xiàng)事情 */
}
}
換上RTOS就是為了提高CPU利用率,使其執(zhí)行多個(gè)任務(wù)(多個(gè)while):
void?Task1(void)
{
/* 初始化 */
while(1)
{
/* 處理事情1 */
}
}
void Task2(void)
{
/* 初始化 */
while(1)
{
/* 處理事情2 */
}
}
void?Task3(void)
void Task4(void)
......
通過對(duì)比裸機(jī)和操作系統(tǒng)的區(qū)別,再結(jié)合開篇的問題,你能聯(lián)想到什么?
裸機(jī)情況下,CPU永遠(yuǎn)都在while(1)大循環(huán)中。那么,在操作系統(tǒng)下,CPU除了執(zhí)行任務(wù)中的while,其他時(shí)間都執(zhí)行到哪兒去了?
答案是:CPU在執(zhí)行操作系統(tǒng)自帶的空閑任務(wù)/線程/進(jìn)程。
OS空閑任務(wù)
我們打開Windows系統(tǒng)的任務(wù)管理器,不操作電腦時(shí),你會(huì)發(fā)現(xiàn)一個(gè)進(jìn)程CPU占有率很高:
沒錯(cuò),這個(gè)進(jìn)行就是系統(tǒng)空閑進(jìn)程。
在RTOS實(shí)時(shí)操作系統(tǒng)中,也有一個(gè)類似這樣的線程(任務(wù)),叫空閑任務(wù)。
uCOS中空閑任務(wù)叫:OS_TaskIdleFreeRTOS中空閑任務(wù)叫:prvIdleTask
當(dāng)然你在線調(diào)試帶有RTOS操作系統(tǒng)的項(xiàng)目時(shí),暫停運(yùn)行代碼,有很大概率CPU會(huì)執(zhí)行到空閑任務(wù)。
比如uCOS空閑函數(shù):
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 */
}
}
其實(shí),你會(huì)發(fā)現(xiàn)這個(gè)系統(tǒng)空閑函數(shù)也沒什么代碼,就是在哪兒“死循環(huán)”。
這里有一個(gè)?OSTaskIdleHook();函數(shù)是提供給用戶的,默認(rèn)情況下,這個(gè)函數(shù)也是啥東西沒有,需要用戶根據(jù)自己情況添加代碼。這里可以參看我之前分享的文章:RTOS中鉤子函數(shù)HOOK的用途及用法。
所以,回到本文的問題:RTOS沒有執(zhí)行任務(wù),CPU在干嘛?
答案是:默認(rèn)情況下,啥都沒干!當(dāng)然,如果你看到CPU太閑了,你也可以讓它干點(diǎn)事。比如在上面的 OSTaskIdleHook() 函數(shù)里面添加一句打印輸出:
printf("CPU在偷懶了...nr");
最后,你對(duì)RTOS實(shí)時(shí)操作系統(tǒng)內(nèi)核了解多少?有多少小伙伴閱讀過內(nèi)核源碼?