3. 时间片轮转调度
任务定义
在RTOS中,当多个任务具有相同优先级时,需要一种机制让它们公平共享CPU。本案例基于FreeRTOS,创建两个同优先级任务,通过配置时间片轮转调度,使两个任务按固定时间片交替执行,并通过串口输出观察调度行为。
时间片轮转原理
FreeRTOS的调度器在Tick中断触发时检查当前任务是否用完了其时间片(由configTICK_RATE_HZ和configUSE_TIME_SLICING决定)。若同优先级就绪队列中存在其他任务,则切换到下一个任务。时间片长度等于一个Tick周期。本案例中两个任务优先级均为1,各自在循环中打印执行计数,通过串口输出可观察到两个任务交替打印。
代码实现
// main.c
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
// 两个任务共享的打印互斥量(可选,用于避免串口输出交错)
static SemaphoreHandle_t xPrintMutex;
// 任务1:打印 'A' 及其执行次数
static void vTaskA(void *pvParameters) {
uint32_t ulCount = 0;
for (;;) {
xSemaphoreTake(xPrintMutex, portMAX_DELAY);
printf("Task A: %lu\r\n", (unsigned long)ulCount++);
xSemaphoreGive(xPrintMutex);
// 空循环,让任务持续占用CPU直到时间片耗尽
for (volatile uint32_t i = 0; i < 10000; i++);
}
}
// 任务2:打印 'B' 及其执行次数
static void vTaskB(void *pvParameters) {
uint32_t ulCount = 0;
for (;;) {
xSemaphoreTake(xPrintMutex, portMAX_DELAY);
printf("Task B: %lu\r\n", (unsigned long)ulCount++);
xSemaphoreGive(xPrintMutex);
for (volatile uint32_t i = 0; i < 10000; i++);
}
}
int main(void) {
// 硬件初始化(时钟、串口等,由平台相关代码提供)
prvSetupHardware();
// 创建打印互斥量
xPrintMutex = xSemaphoreCreateMutex();
// 创建两个同优先级任务(优先级均为1)
xTaskCreate(vTaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(vTaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
// 启动调度器
vTaskStartScheduler();
// 正常不会到达这里
for (;;);
return 0;
}
FreeRTOSConfig.h 关键配置
#define configUSE_PREEMPTION 1 // 使能抢占式调度
#define configUSE_TIME_SLICING 1 // 使能时间片轮转(默认开启)
#define configTICK_RATE_HZ ( 1000 ) // Tick频率1kHz,时间片=1ms
#define configMAX_PRIORITIES 5
时间片调度时序
构建与运行
- 依赖:FreeRTOS内核源码(V10.x及以上),平台相关移植文件(如STM32、QEMU等),以及可用的串口打印函数
printf重定向。 - 编译:将
main.c加入工程,确保FreeRTOSConfig.h中configUSE_TIME_SLICING为1,configTICK_RATE_HZ设为1000。 - 运行:烧录或启动系统,打开串口终端(波特率与平台匹配,通常115200)。
验证方法与判定标准
验证步骤:
- 观察串口输出,应看到
Task A和Task B交替打印,且各自计数递增。 - 统计连续打印次数:在1秒内(约1000个Tick),Task A和Task B各打印约500次(允许±10%误差,因printf耗时影响)。
- 若将
configUSE_TIME_SLICING改为0,则两个任务不再交替,一个任务会持续独占CPU(除非被更高优先级任务抢占或阻塞),此时只能看到单个任务持续打印。
判定标准:串口输出中Task A与Task B交替出现,且每个任务打印计数单调递增,无卡死或异常跳变,即证明时间片轮转调度生效。