3. 时间片轮转调度
任务目标
在 VxWorks 中创建两个同优先级任务,通过配置时间片轮转调度(Round-Robin),使两个任务按固定时间片交替占用 CPU,从而验证同优先级任务间的公平调度行为。
核心原理
VxWorks 默认使用基于优先级的抢占式调度,同优先级任务间不主动让出 CPU。启用时间片轮转后,系统为每个就绪的同优先级任务分配固定长度的时间片(tick 数),时间片耗尽后任务被移到就绪队列尾部,下一个同优先级任务获得 CPU。本案例通过两个任务各自打印执行序号来直观观察轮转效果。
完整实现代码
/* rr_demo.c - 时间片轮转调度演示 */
#include <vxWorks.h>
#include <taskLib.h>
#include <stdio.h>
#include <tickLib.h>
/* 任务函数:打印任务名与执行计数 */
static void rrTask(const char *name)
{
int i;
for (i = 0; i < 5; i++) {
printf("%s: 第 %d 次执行\n", name, i + 1);
taskDelay(1); /* 延时1个tick,便于观察轮转 */
}
}
/* 任务入口:创建两个同优先级任务并启动轮转调度 */
void rrDemo(void)
{
int priority = 100; /* 同优先级 */
int options = VX_FP_TASK; /* 浮点任务选项 */
int stackSize = 20000; /* 栈大小(字节) */
/* 创建两个同优先级任务 */
taskSpawn("tRR1", priority, options, stackSize,
(FUNCPTR)rrTask, (int)"Task-1", 0,0,0,0,0,0,0,0,0);
taskSpawn("tRR2", priority, options, stackSize,
(FUNCPTR)rrTask, (int)"Task-2", 0,0,0,0,0,0,0,0,0);
/* 启用时间片轮转:时间片为 3 个 tick */
kernelTimeSlice(3);
}
编译与运行
- 将上述代码保存为
rr_demo.c,加入 VxWorks 工程编译链接。 - 在 VxWorks shell 中调用入口函数:
rrDemo - 观察串口终端输出。
验证方法与判定标准
预期输出特征:两个任务交替打印执行信息,且同一任务连续打印次数不超过约3次(对应3个tick时间片)。典型输出片段如下:
Task-1: 第 1 次执行
Task-1: 第 2 次执行
Task-2: 第 1 次执行
Task-2: 第 2 次执行
Task-1: 第 3 次执行
...
通过条件:
- 两个任务均完成5次打印,无任务饿死;
- 输出中 Task-1 与 Task-2 交替出现,而非一个任务连续执行完所有打印;
- 若注释掉
kernelTimeSlice(3)后重新运行,则第一个任务会连续打印5次后才轮到第二个任务——通过对比可确认时间片轮转已生效。
关键说明
kernelTimeSlice()参数单位为系统 tick,需在工程中配置系统 tick 频率(通常为 60Hz 或 100Hz)。- 任务内
taskDelay(1)用于降低打印速度,避免输出过快难以观察;实际轮转由内核时间片中断驱动,不依赖该延时。 - 若需恢复默认的非轮转调度,调用
kernelTimeSlice(0)即可。
上图展示了时间片轮转的执行序列:每个时间片为 3 个 tick,Task-1 与 Task-2 交替占用 CPU,形成公平调度。图中每个色块代表一个完整时间片,任务在时间片耗尽后让出处理器。