2. 任务优先级与调度
任务目标
创建两个不同优先级的VxWorks任务,通过高优先级任务主动延迟释放CPU、低优先级任务持续运行的方式,观察高优先级任务就绪后立即抢占低优先级任务执行的现象,验证VxWorks基于优先级的抢占式调度机制。
实现原理
VxWorks默认采用基于优先级的抢占式调度(Priority-Based Preemptive Scheduling)。当高优先级任务进入就绪态时,系统立即保存当前运行任务(低优先级)的上下文,切换到高优先级任务执行。本案例通过两个任务交替打印运行标记,直观展示抢占过程。
完整代码
/* task_priority_demo.c - VxWorks任务优先级抢占调度演示 */
#include <vxWorks.h>
#include <taskLib.h>
#include <stdio.h>
/* 任务函数:低优先级任务,持续循环运行 */
void lowPriorityTask(void)
{
int count = 0;
while (1)
{
printf("[LOW] running, count = %d\n", count++);
taskDelay(1); /* 主动让出CPU,给高优先级任务运行机会 */
}
}
/* 任务函数:高优先级任务,周期性运行 */
void highPriorityTask(void)
{
int count = 0;
while (1)
{
printf("[HIGH] running, count = %d\n", count++);
taskDelay(sysClkRateGet() / 2); /* 延迟0.5秒 */
}
}
/* 创建两个任务的入口函数 */
void priorityDemoStart(void)
{
/* 创建低优先级任务:优先级100 */
taskSpawn("tLow", 100, 0, 0x2000, (FUNCPTR)lowPriorityTask, 0,0,0,0,0,0,0,0,0,0);
/* 创建高优先级任务:优先级50(数值越小优先级越高) */
taskSpawn("tHigh", 50, 0, 0x2000, (FUNCPTR)highPriorityTask, 0,0,0,0,0,0,0,0,0,0);
}
运行与验证
环境要求:VxWorks 6.x/7.x 或 Wind River Workbench 仿真环境(VxSim)。
运行步骤:
- 将上述代码编译链接到VxWorks镜像或作为可下载内核模块(DKM)加载;
- 在Shell中调用入口函数:
priorityDemoStart; - 观察Shell输出。
预期输出与判定标准:
输出应呈现以下特征,满足即判定通过:
- 启动后首先看到
[LOW]任务打印若干行(因为低优先级任务先被创建并立即运行); - 约0.5秒后,高优先级任务第一次就绪,立即抢占CPU,输出
[HIGH]打印; - 此后输出呈现明显的交替模式:高优先级任务每0.5秒运行一次并打印,低优先级任务在高优先级任务延迟期间运行并打印;
- 高优先级任务每次就绪后,低优先级任务的打印会立即中断,证明抢占发生。
典型输出片段(示例):
[LOW] running, count = 0
[LOW] running, count = 1
[LOW] running, count = 2
[HIGH] running, count = 0
[LOW] running, count = 3
[LOW] running, count = 4
[HIGH] running, count = 1
[LOW] running, count = 5
...
验证要点:若将两个任务的优先级互换(高优先级任务延迟时间短、低优先级任务延迟时间长),则低优先级任务几乎无法获得CPU——这进一步验证了抢占调度的效果。可通过taskPrioritySet动态调整优先级,观察调度行为随之改变。
关键说明
- VxWorks优先级数值范围0~255,数值越小优先级越高;
taskDelay使任务进入延迟睡眠状态,主动释放CPU;- 若删除低优先级任务中的
taskDelay(1),低优先级任务将独占CPU,高优先级任务无法运行——这体现了VxWorks时间片轮转默认关闭的特性; - 本案例仅演示优先级抢占,不涉及同优先级任务间的时间片轮转调度。