什么是时间片
时间片是一个任务被任务调度管理器强制切换出CPU之前连续运行的最长时间。
FreeRTOS 中,时间片的长度固定为 1 个 tick。
tick的时长可以通过配置文件FreeRTOSConfig.h中的宏定义configTICK_RATE_HZ修改。
每个时间片的长度 (秒) = 1 / configTICK_RATE_HZ。
// 将Tick频率设置为1000Hz,此时1个Tick = 1ms
#define configTICK_RATE_HZ 1000
什么是时间片轮转
时间片轮转是一种任务调度算法,让多个同优先级任务轮流使用 CPU,每个任务每次运行一个固定长度的时间片,时间片用完后强制切换到下一个任务。
时间片轮转的触发机制
void vTask1(void *pvParameters)
{
for(;;)
{
printf("Task1 running\r\n");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
这里printf() 执行时间极短(比如 10 微秒),然后任务主动调用 vTaskDelay(),立即进入阻塞态。
任务在 printf() 刚执行完就主动让出了 CPU。时间片轮转并没有触发。
因为时间片轮转触发的前提是:任务连续运行满 1 个 tick 且没有主动让出。
任务在 1 个 tick 还没到(才运行了 10 微秒)就主动调用 vTaskDelay() 阻塞了,所以:
✅ 触发的是 vTaskDelay() 的阻塞机制。
❌ 没有触发时间片轮转机制。
void Task_TimeSlice(void *pv) {
while(1) {
for(int i = 0; i < 1000000; i++); // 耗时 > 1 tick
vTaskDelay(1000);
}
}
即使后面有 vTaskDelay(1000),for(int i = 0; i < 1000000; i++)超过1 tick,CPU也会强制进行任务切换。
如果不想比打断可以使用临界区:
taskENTER_CRITICAL();
for(int i = 0; i < 1000000; i++); // 不会被中断
taskEXIT_CRITICAL();
时间片轮转的开关
- configUSE_TIME_SLICING = 1 (开启):系统会在每个Tick中断时,检查当前优先级下是否还有其他就绪任务。如果有,就强制切换到下一个任务,实现时间片轮转调度。
- configUSE_TIME_SLICING = 0 (关闭):系统关闭自动轮转。此时,同优先级任务之间不会因为Tick中断而自动切换,必须通过任务主动阻塞(如调用vTaskDelay)或主动让出(如调用taskYIELD())才能发生切换。
注意:configUSE_TIME_SLICING 只有开(1)和关(0)两种状态。