在FreeRTOS中,任务调度是根据任务的优先级和状态来决定的。理解如何在时间片轮转机制下管理任务对于编写高效的实时系统至关重要。以下是FreeRTOS任务调度和时间片轮转机制的详细总结:
任务状态
任务在FreeRTOS中可以有以下几种状态:
- 运行态(Running):当前正在使用CPU的任务。
- 就绪态(Ready):准备执行但等待CPU的任务。
- 阻塞态(Blocked):等待某个事件或资源而无法执行的任务。
- 挂起态(Suspended):任务被暂停,不会被调度执行。
任务优先级
FreeRTOS使用优先级调度,优先级高的任务总是优先执行。当多个任务有相同的优先级时,调度器会根据时间片轮转机制在它们之间切换。
时间片轮转机制
时间片轮转(Time Slicing)是一种确保同优先级任务能够公平共享CPU资源的机制。每个同优先级任务在一段时间(时间片)内独占CPU,时间片用尽后,调度器将CPU分配给下一个同优先级的就绪任务。
任务从阻塞态变为就绪态
当一个任务从阻塞态变为就绪态时,如果其优先级高于当前运行任务的优先级,调度器会立即切换到该任务执行。然而,如果它的优先级与当前运行任务相同,FreeRTOS不会立即进行任务切换,当前任务会继续执行直到以下情况之一发生:
- 当前任务主动让出CPU:当前运行任务调用
taskYIELD()
函数,主动放弃CPU使用权。 - 当前任务进入阻塞态:当前运行任务因等待某个事件或资源而进入阻塞状态。
- 时间片到期:在时间片轮转机制下,当前任务的时间片用尽,调度器会将CPU分配给下一个同优先级的就绪任务。
示例说明
假设有两个任务任务1和任务2,优先级相同,且启用了时间片轮转机制:
- 任务1正在运行:任务1当前占用CPU。
- 任务2处于阻塞态:任务2在等待队列中的值,处于阻塞状态。
- 任务2变为就绪态:当任务2从阻塞态变为就绪态时,调度器不会立即切换到任务2,因为任务1仍在运行。
- 时间片到期:当任务1的时间片用尽,调度器会在任务1和任务2之间切换,任务2将得到执行机会。
示例:任务1一直执行,任务2得不到CPU资源
假设任务1是一个长期运行的任务,不主动让出CPU且不会进入阻塞态,而任务2需要等待队列中的值:
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
// 任务函数1
void vTask1(void *pvParameters)
{
for (;;)
{
// 模拟长时间运行的任务
// 不调用taskYIELD()或进入阻塞态
}
}
// 任务函数2
void vTask2(void *pvParameters)
{
QueueHandle_t xQueue = (QueueHandle_t)pvParameters;
int value;
for (;;)
{
// 等待从队列中获取值
if (xQueueReceive(xQueue, &value, portMAX_DELAY) == pdPASS)
{
// 模拟处理值
// 不进入长时间运行,处理完后继续等待
}
}
}
int main(void)
{
QueueHandle_t xQueue;
// 创建队列
xQueue = xQueueCreate(10, sizeof(int));
if (xQueue != NULL)
{
// 创建任务1和任务2,优先级相同
xTaskCreate(vTask1, "Task 1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
xTaskCreate(vTask2, "Task 2", configMINIMAL_STACK_SIZE, xQueue, tskIDLE_PRIORITY + 1, NULL);
// 启动调度器
vTaskStartScheduler();
}
// 调度器启动失败
for (;;);
return 0;
}
在这个示例中,任务1是一个长期运行的任务,不会主动让出CPU或进入阻塞态,而任务2需要从队列中获取值。尽管任务2在某个时刻从阻塞态变为就绪态,但由于任务1一直在运行且优先级相同,任务2无法抢占CPU资源,无法得到执行机会。
关键点总结
- 同优先级任务不会立即抢占:当一个任务从阻塞态变为就绪态时,不会立即抢占当前运行的同优先级任务的CPU资源。
- 时间片轮转确保公平:启用时间片轮转机制后,同优先级任务会在每个时间片到期时得到公平的执行机会。
- 任务切换的触发条件:任务主动让出CPU、任务进入阻塞态以及时间片用尽都会触发任务切换。
- 长期运行任务的影响:如果一个长期运行的任务不主动让出CPU或进入阻塞态,即使启用了时间片轮转机制,其他同优先级任务也可能无法得到执行机会。
通过合理利用FreeRTOS的任务调度和时间片轮转机制,可以有效地管理同优先级任务的执行,确保系统的实时性和响应性。