微信公眾號(hào) | strongerHuang
RTOS兩任務(wù)優(yōu)先級(jí)相同,誰先執(zhí)行?這個(gè)問題把很多初學(xué)的小伙伴難住了,今天就來結(jié)合案例給大家簡(jiǎn)單描述一下。
什么是RTOS任務(wù)優(yōu)先級(jí)?
在RTOS中,每一個(gè)任務(wù)(Task)都會(huì)分配一個(gè)優(yōu)先級(jí),在所有就緒的任務(wù)中,任務(wù)優(yōu)先級(jí)越高就優(yōu)先執(zhí)行。
任務(wù)優(yōu)先級(jí)在我們創(chuàng)建任務(wù)的時(shí)候,就要賦予(設(shè)置)一個(gè)優(yōu)先級(jí)值,比如FreeRTOS創(chuàng)建任務(wù):
/* APP任務(wù)優(yōu)先級(jí) */
#define?APP_TASK_PRIORITY?????????6
/* 創(chuàng)建應(yīng)用程序(APP任務(wù)) */
xTaskCreate(APP_Task, "APP_Task", 128, NULL, APP_TASK_PRIORITY, NULL);
6 代表?APP_Task?任務(wù)優(yōu)先級(jí)(宏定義為6),在FreeRTOS系統(tǒng)中,這個(gè)數(shù)字越大,優(yōu)先級(jí)越高。
然而,并不是每一款RTOS任務(wù)優(yōu)先級(jí)數(shù)值越大優(yōu)先級(jí)越大,有些RTOS則相反。
比如:UCOS中,優(yōu)先級(jí)數(shù)值越小,優(yōu)先級(jí)則越大。
RTOS兩任務(wù)優(yōu)先級(jí)相同,誰先執(zhí)行?
在FreeRTOS系統(tǒng)中,如果兩個(gè)任務(wù)優(yōu)先級(jí)(數(shù)值)相同,誰先執(zhí)行?
這里結(jié)合代碼,和實(shí)驗(yàn)現(xiàn)象給大家描述一下。
1、創(chuàng)建兩個(gè)相同優(yōu)先級(jí)的任務(wù)
比如:APP_Task1和APP_Task2,優(yōu)先級(jí)都為6
#define APP_TASK1_PRIORITY 6 //APP任務(wù)1優(yōu)先級(jí)
#define APP_TASK2_PRIORITY 6 //APP任務(wù)1優(yōu)先級(jí)
xTaskCreate(APP_Task1, "APP_Task1", 128, NULL, APP_TASK1_PRIORITY, NULL);
xTaskCreate(APP_Task2, "APP_Task2", 128, NULL, APP_TASK2_PRIORITY, NULL);
2、兩個(gè)應(yīng)用程序
比如:都是累加一個(gè)值,并隔一段時(shí)間打印累加值。
static uint32_t Task1_Cnt = 0;
static uint32_t Task2_Cnt = 0;
static void APP_Task1(void *pvParameters)
{
vTaskDelay(100);
while(1)
{
Task1_Cnt++;
if(0 == (Task1_Cnt%1000000))
{
printf("Task1_Cnt=%d",Task1_Cnt);
}
}
}
//作者:strongerHuang
static void APP_Task2(void *pvParameters)
{
vTaskDelay(200);
while(1)
{
Task2_Cnt++;
if(0 == (Task2_Cnt%1000000))
{
printf("Task2_Cnt=%d",Task2_Cnt);
}
}
}
3、實(shí)驗(yàn)現(xiàn)象
輪流打印數(shù)值,如下圖:
通過實(shí)驗(yàn)現(xiàn)象,你肯定猜得出結(jié)論:FreeRTOS兩個(gè)優(yōu)先級(jí)相同的任務(wù),它們是按照時(shí)間片輪轉(zhuǎn)的方式進(jìn)行調(diào)度,也就是交替執(zhí)行。
當(dāng)然,這里有一個(gè)前提:任務(wù)要處于就緒狀態(tài)。如果任務(wù)是阻塞狀態(tài),則改任務(wù)不會(huì)被輪轉(zhuǎn)執(zhí)行。
比如:在任務(wù)1中增加系統(tǒng)延時(shí)(阻塞),則任務(wù)1不會(huì)被執(zhí)行,看實(shí)驗(yàn)現(xiàn)象,如下圖:
補(bǔ)充說明
上面只是針對(duì)FreeRTOS實(shí)時(shí)操作系統(tǒng)而言,并不是所有RTOS都是這樣的。
像UCOS就不一樣,創(chuàng)建兩個(gè)相同優(yōu)先級(jí)的任務(wù),只有第一個(gè)(先創(chuàng)建的任務(wù))優(yōu)先被執(zhí)行,第二個(gè)不會(huì)被執(zhí)行。
還是一樣,給大家看類似的源碼和實(shí)驗(yàn)現(xiàn)象。
1、創(chuàng)建兩個(gè)相同優(yōu)先級(jí)的任務(wù)
同樣:APP_Task1和APP_Task2,優(yōu)先級(jí)都為6
#define TASK1_PRIO 6
#define TASK2_PRIO 6
/* 創(chuàng)建任務(wù)1 */
OSTaskCreateExt((void (*)(void *)) APP_Task1,
(void *) 0,
(OS_STK *)&Task1_Stk[TASK1_STK_SIZE-1],
(INT8U ) TASK1_PRIO,
(INT16U ) TASK1_PRIO,
(OS_STK *)&Task1_Stk[0],
(INT32U ) TASK1_STK_SIZE,
(void *) 0,
(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
/* 創(chuàng)建任務(wù)2 */
OSTaskCreateExt((void (*)(void *)) APP_Task2,
(void *) 0,
(OS_STK *)&Task2_Stk[TASK2_STK_SIZE-1],
(INT8U ) TASK2_PRIO,
(INT16U ) TASK2_PRIO,
(OS_STK *)&Task2_Stk[0],
(INT32U ) TASK2_STK_SIZE,
(void *) 0,
(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
2、兩個(gè)應(yīng)用程序
同樣:也是累加一個(gè)值,并隔一段時(shí)間打印累加值。
static uint32_t Task1_Cnt = 0;
static uint32_t Task2_Cnt = 0;
void APP_Task1(void *pvParameters)
{
OSTimeDly(100);
while(1)
{
Task1_Cnt++;
if(0 == (Task1_Cnt%1000000))
{
printf("Task1_Cnt=%d",Task1_Cnt);
}
}
}
//作者:strongerHuang
void APP_Task2(void *pvParameters)
{
OSTimeDly(200);
while(1)
{
Task2_Cnt++;
if(0 == (Task2_Cnt%1000000))
{
printf("Task2_Cnt=%d",Task2_Cnt);
}
}
}
3、實(shí)驗(yàn)現(xiàn)象
只有先被創(chuàng)建的任務(wù)1有打印數(shù)值,如下圖:
那么,為什么會(huì)出現(xiàn)這樣的情況呢?
答案是:UCOS不允許相同優(yōu)先級(jí)的任務(wù)。
如果某一優(yōu)先級(jí)(如6)的任務(wù)已經(jīng)被創(chuàng)建,再次創(chuàng)建該優(yōu)先級(jí)(6)的任務(wù)會(huì)創(chuàng)建失敗。這里可以找到內(nèi)核源碼:
所以,并不是所有RTOS都可以創(chuàng)建兩個(gè)相同優(yōu)先級(jí)的任務(wù),具體要看RTOS自身的情況。
最后,你明白了嗎?