RTOS两任务优先级相同,谁先执行?

关注+星标公众,不错过精彩内容

72d049e2378ae0ad5ff2be10d5972087.gif

作者 | strongerHuang

微信公众号 | strongerHuang

RTOS两任务优先级相同,谁先执行?这个问题把很多初学的小伙伴难住了,今天就来结合案例给大家简单描述一下。

什么是RTOS任务优先级?

在RTOS中,每一个任务(Task)都会分配一个优先级,在所有就绪的任务中,任务优先级越高就优先执行。

任务优先级在我们创建任务的时候,就要赋予(设置)一个优先级值,比如FreeRTOS创建任务:

/* APP任务优先级 */
#define APP_TASK_PRIORITY         6


/* 创建应用程序(APP任务) */
xTaskCreate(APP_Task, "APP_Task", 128, NULL, APP_TASK_PRIORITY, NULL);

6 代表 APP_Task 任务优先级(宏定义为6),在FreeRTOS系统中,这个数字越大,优先级越高。

然而,并不是每一款RTOS任务优先级数值越大优先级越大,有些RTOS则相反。

比如:UCOS中,优先级数值越小,优先级则越大。

RTOS两任务优先级相同,谁先执行?

在FreeRTOS系统中,如果两个任务优先级(数值)相同,谁先执行?

这里结合代码,和实验现象给大家描述一下。

1、创建两个相同优先级的任务

比如:APP_Task1和APP_Task2,优先级都为6

#define APP_TASK1_PRIORITY        6                        //APP任务1优先级
#define APP_TASK2_PRIORITY        6                        //APP任务1优先级


xTaskCreate(APP_Task1, "APP_Task1", 128, NULL, APP_TASK1_PRIORITY, NULL);
xTaskCreate(APP_Task2, "APP_Task2", 128, NULL, APP_TASK2_PRIORITY, NULL);

2、两个应用程序

比如:都是累加一个值,并隔一段时间打印累加值。

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、实验现象

轮流打印数值,如下图:

021c2be1415304ad0b3792a1ad5d77ac.png

通过实验现象,你肯定猜得出结论:FreeRTOS两个优先级相同的任务,它们是按照时间片轮转的方式进行调度,也就是交替执行

当然,这里有一个前提:任务要处于就绪状态。如果任务是阻塞状态,则该任务不会被轮转执行。

比如:在任务1中增加系统延时(阻塞),则任务1不会被执行,看实验现象,如下图:

e9d9a9889336b8b0b0d20a884168fbbc.png

补充说明

上面只是针对FreeRTOS实时操作系统而言,并不是所有RTOS都是这样的。

像UCOS2就不一样,创建两个相同优先级的任务,只有第一个(先创建的任务)优先被执行,第二个不会被执行。

还是一样,给大家看类似的源码和实验现象。

1、创建两个相同优先级的任务

同样:APP_Task1和APP_Task2,优先级都为6

#define TASK1_PRIO                             6
#define TASK2_PRIO                             6


/* 创建任务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));


/* 创建任务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、两个应用程序

同样:也是累加一个值,并隔一段时间打印累加值。

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、实验现象

只有先被创建的任务1有打印数值,如下图:

62e3e94b57f7e53a6603ada80ea662d5.png

那么,为什么会出现这样的情况呢?

答案是:UCOS2不允许相同优先级的任务(当然,UCOS3是支持的)。

如果某一优先级(如6)的任务已经被创建,再次创建该优先级(6)的任务会创建失败。这里可以找到内核源码:

5c5da34b3ec1eeee78d4890a91aa097e.png

所以,并不是所有RTOS都可以创建两个相同优先级的任务,具体要看RTOS自身的情况。

最后,你明白了吗?

------------ END ------------

0b705fb4b6ae89d128626db21b084ddb.gif

●专栏《嵌入式工具

●专栏《嵌入式开发》

●专栏《Keil教程》

●嵌入式专栏精选教程

关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

点击“阅读原文”查看更多分享。

### RTOS任务优先级的设置与管理 在实时操作系统(RTOS)中,任务优先级的设置和管理是核心功能之一。以下是关于任务优先级的相关概念及其重要性的详细介绍。 #### 1. **任务优先级划分** 在 RTOS 中,每个任务会被分配一个优先级,通常是通过整数表示。较高的数值代表更高的优先级[^1]。这意味着,在调度过程中,具有较高优先级任务会优先获得 CPU 的执行权。这种机制确保了时间敏感型任务能够在规定的时间范围内完成。 #### 2. **抢占式调度** RTOS 常采用抢占式调度策略。在这种模式下,当一个高优先级任务进入就绪状态时,RTOS 将中断当前正在运行的低优先级任务,并立即将 CPU 切换至高优先级任务[^1]。这种方式显著提高了系统的实时响应能力,特别适用于需要快速反应的应用场景。 #### 3. **动态优先级调整** 部分 RTOS 支持动态调整任务优先级的功能。这使得系统可以根据实际负载情况或特定任务的重要程度实时修改其优先级[^1]。例如,在某些紧急情况下,原本较低优先级任务可以通过提升优先级来迅速获取资源,从而增强系统的灵活性和适应性。 #### 4. **优先级反转及解决方案** 优先级反转是一种常见问题,指的是由于资源共享而导致高优先级任务被阻塞的现象。具体来说,如果某个低优先级任务持有高优先级任务所需资源,则后者不得不等待前者释放资源[^2]。为了解决此问题,许多 RTOS 提供了优先级继承机制——即暂时提高持有资源的低优先级任务优先级,使其达到与请求者相同的级别,直到资源释放为止[^3]。 #### 5. **上下文切换** 为了实现高效的优先级任务切换,RTOS 需要妥善处理上下文切换过程。每当发生任务切换时,都需要保存当前任务的状态信息(如寄存器值、堆栈指针等),并将这些数据恢复到目标任务上[^3]。因此,优化上下文切换开销对于维持整体性能至关重要。 #### 6. **FreeRTOS 特殊考虑** 以 FreeRTOS 为例,在其中断优先级配置方面需要注意的是:只有低于一定阈值(比如 5 级别以下)的中断才能安全调用 FreeRTOS API 函数;同时建议将全部四位用于定义抢占优先级以便更好地控制行为[^4]。此外值得注意的一点是在 FreeRTOS 下,虽然中断优先级遵循“数值越小越优先”的原则,但任务优先级却正好相反,“数值越大越优先”。 ```c // 示例代码展示如何在 FreeRTOS 中设置任务优先级 void vTaskFunction(void *pvParameters) { while (true) { // 执行任务逻辑... } } int main() { const UBaseType_t uxPriority = 2; // 定义任务优先级为2 xTaskCreate(vTaskFunction, "TaskName", configMINIMAL_STACK_SIZE, NULL, uxPriority, NULL); vTaskStartScheduler(); } ``` 以上是对 RTOS任务优先级设定及相关概念的一个全面概述。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

strongerHuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值