实时操作系统(RTOS)--任务状态

一 任务状态介绍:

实时操作系统(RTOS)中的任务通常具有多种状态,这些状态描述了任务在其生命周期中的不同阶段。以下是一些常见的任务状态及其解释,并附带一个简化的示例:

  1. 就绪态(Ready)

    • 任务已经准备好执行,所有必要资源都已经准备就绪,只等待被RTOS调度器选中并分配CPU时间。 示例:任务A被创建后,被赋予了足够的堆栈空间和优先级,等待调度器调度。
  2. 运行态(Running)

    • 任务正在执行,占据了CPU资源。 示例:任务A被调度器选中,其上下文被加载到CPU寄存器中,开始执行任务代码。
  3. 阻塞态(Blocked)

    • 任务暂时不能执行,通常是因为等待某些外部事件,如I/O操作完成、定时器到期、信号量或互斥量被释放等。 示例:任务A调用了vTaskDelay()函数等待一定时间间隔,这时任务A进入了阻塞态,直到延时期满后才会变为就绪态。
  4. 挂起态(Suspended)

    • 任务被人为挂起,不会参与调度,除非通过API函数恢复其就绪状态。 示例:任务A通过API函数vTaskSuspend()被手动挂起,不再参与调度,直到通过vTaskResume()恢复。
  5. 终止态(Terminated)

    • 任务执行完毕或被删除,生命周期结束,不再参与调度。 示例:任务A完成了所有预定工作并通过vTaskDelete()函数被删除,这时任务A处于终止态,其占用的系统资源将被回收。

下面是一个简化的示例代码片段,展示了任务在不同状态之间的切换:

C

1#include <freertos/FreeRTOS.h>
2#include <freertos/task.h>
3
4void vTaskFunction(void *pvParameters)
5{
6    while (1)
7    {
8        // 任务开始时,处于就绪态
9        printf("Task running...\n");
10
11        // 进入阻塞态,等待1秒钟
12        vTaskDelay(pdMS_TO_TICKS(1000));
13
14        // 延时过后,任务再次变为就绪态
15        printf("Task resumed after delay...\n");
16
17        // 假设某个条件满足,任务被挂起
18        if (someCondition)
19            vTaskSuspend(NULL);
20
21        // 当条件改变,任务被恢复
22        if (conditionChanged)
23            vTaskResume(NULL);
24        
25        // 如果任务要结束,可以删除自身
26        if (shouldTerminate)
27            vTaskDelete(NULL);
28    }
29}
30
31int main()
32{
33    // 创建任务并初始化,此时任务处于就绪态
34    xTaskCreate(vTaskFunction, "MyTask", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
35
36    // 启动RTOS调度器
37    vTaskStartScheduler();
38
39    // 实际永远不会达到此处,因为调度器无限循环
40    return 0;
41}

在上述示例中,任务在vTaskDelay()函数调用后进入阻塞态,当延时期满后恢复到就绪态。如果满足特定条件,任务还会经历挂起和恢复的过程,最后根据需要还可删除自身。调度器会根据任务状态和优先级做出调度决策,确保实时性和任务间的协调执行。

二 任务阻塞态实例

在实时操作系统(RTOS)中,任务在等待I/O操作完成、定时器到期、信号量或互斥量被释放等情况下的实际例子如下:1. **等待I/O操作完成**:


   #include <freertos/FreeRTOS.h>
   #include <driver/gpio.h>

   void vTaskWaitForIO(void *pvParameters)
   {
       gpio_config_t ioConfig;
       ioConfig.pin_bit_mask = GPIO_SEL_4; // 假设配置GPIO4引脚
       ioConfig.mode = GPIO_MODE_INPUT;
       gpio_config(&ioConfig);

       while (1)
       {
           // 任务等待I/O操作完成(例如,等待按键按下)
           while (gpio_get_level(GPIO_NUM_4) == 0) 
           {
               // I/O操作尚未完成(按键未按下),任务进入阻塞态
               vTaskDelay(pdMS_TO_TICKS(10)); // 微小延时,防止CPU过度占用
           }

           // I/O操作完成(按键被按下),任务继续执行
           printf("Button pressed!\n");
       }
   }

   int main()
   {
       xTaskCreate(vTaskWaitForIO, "IO_Wait_Task", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
       vTaskStartScheduler();
       return 0;
   }


   上述示例中,任务一直在等待GPIO引脚电平变化,当电平变化(例如,按键按下)时,任务从阻塞态恢复到就绪态。2. **等待定时器到期**:
   


   #include <freertos/FreeRTOS.h>
   #include <freertos/timers.h>

   TimerHandle_t xTimer;

   void vTaskWaitForTimer(void *pvParameters)
   {
       // 创建一个周期性定时器,周期为1秒
       xTimer = xTimerCreate("Periodic_Timer", pdMS_TO_TICKS(1000), pdTRUE, NULL, NULL);

       if (xTimer != NULL)
       {
           // 启动定时器
           xTimerStart(xTimer, portMAX_DELAY);

           while (1)
           {
               // 任务等待定时器到期
               if (xTimerIsTimerActive(xTimer))
               {
                   // 定时器还未到期,任务进入阻塞态
                   vTaskDelay(pdMS_TO_TICKS(10));
               }
               else
               {
                   // 定时器到期,任务继续执行
                   printf("Timer expired!\n");
                   // 重新启动定时器
                   xTimerStart(xTimer, portMAX_DELAY);
               }
           }
       }
   }

   int main()
   {
       xTaskCreate(vTaskWaitForTimer, "Timer_Wait_Task", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
       vTaskStartScheduler();
       return 0;
   }


   在这个例子中,任务一直在等待定时器到期,当定时器到期时,任务从阻塞态恢复到就绪态。3. **等待信号量或互斥量被释放**:


   #include <freertos/FreeRTOS.h>
   #include <freertos/semphr.h>

   SemaphoreHandle_t xSemaphore;

   void vTaskWaitForSemaphore(void *pvParameters)
   {
       xSemaphore = xSemaphoreCreateBinary();

       if (xSemaphore != NULL)
       {
           // 其他任务或中断可能释放信号量
           // 假设一开始信号量未释放,任务等待信号量
           while (xSemaphoreTake(xSemaphore, portMAX_DELAY) != pdTRUE)
           {
               // 信号量尚未释放,任务进入阻塞态
           }

           // 信号量被释放,任务继续执行
           printf("Semaphore taken!\n");
           // 进行相应处理后释放信号量,以便其他任务可以获取
           xSemaphoreGive(xSemaphore);
       }
   }

   void vOtherTaskReleasesSemaphore(void *pvParameters)
   {
       // 其他任务在适当的时候释放信号量
       vTaskDelay(pdMS_TO_TICKS(5000)); // 延迟5秒后释放
       xSemaphoreGive(xSemaphore);
   }

   int main()
   {
       xTaskCreate(vTaskWaitForSemaphore, "Semaphore_Wait_Task", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
       xTaskCreate(vOtherTaskReleasesSemaphore, "Semaphore_Release_Task", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
       vTaskStartScheduler();
       return 0;
   }


   在这个例子中,`vTaskWaitForSemaphore`任务在等待信号量被释放,当`vOtherTaskReleasesSemaphore`任务释放信号量时,`vTaskWaitForSemaphore`任务从阻塞态恢复到就绪态。同样的逻辑也适用于互斥量(Mutexes)。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值