2. 任务优先级抢占
任务目标
创建两个不同优先级的VxWorks任务,通过共享变量的输出顺序,验证高优先级任务能够抢占低优先级任务的CPU执行权。
核心原理
VxWorks采用基于优先级的抢占式调度。当高优先级任务就绪时,系统立即保存当前运行任务的上下文,切换到高优先级任务执行。本案例通过两个任务循环打印各自计数器,观察高优先级任务(priority=100)始终先于低优先级任务(priority=150)完成每一轮打印,从而证明抢占行为。
完整实现代码
/* task_preempt_demo.c - VxWorks任务优先级抢占验证 */
#include <vxWorks.h>
#include <taskLib.h>
#include <stdio.h>
/* 共享标志:用于同步两个任务的启动 */
static volatile int startFlag = 0;
/* 低优先级任务:priority = 150 */
static void lowPriorityTask(void)
{
int i;
while (startFlag == 0) /* 等待启动信号 */
taskDelay(1);
for (i = 0; i < 5; i++) {
printf("[LOW ] Round %d\n", i + 1);
taskDelay(10); /* 主动让出CPU,给高优先级任务运行机会 */
}
}
/* 高优先级任务:priority = 100 */
static void highPriorityTask(void)
{
int i;
while (startFlag == 0)
taskDelay(1);
for (i = 0; i < 5; i++) {
printf("[HIGH] Round %d\n", i + 1);
taskDelay(10);
}
}
/* 任务创建入口 */
void taskPreemptDemo(void)
{
int tidLow, tidHigh;
/* 创建低优先级任务(priority=150) */
tidLow = taskSpawn("tLow", 150, 0, 0x2000,
(FUNCPTR)lowPriorityTask, 0,0,0,0,0,0,0,0,0,0);
if (tidLow == ERROR) {
printf("Failed to spawn low priority task\n");
return;
}
/* 创建高优先级任务(priority=100) */
tidHigh = taskSpawn("tHigh", 100, 0, 0x2000,
(FUNCPTR)highPriorityTask, 0,0,0,0,0,0,0,0,0,0);
if (tidHigh == ERROR) {
printf("Failed to spawn high priority task\n");
return;
}
/* 释放启动信号 */
startFlag = 1;
}
编译与运行
- 在VxWorks开发环境(如Workbench)中创建C文件,将上述代码粘贴保存为
task_preempt_demo.c。 - 将该文件添加到当前VxWorks镜像工程或可加载模块工程中。
- 编译生成可加载模块(.out文件)或直接编译进VxWorks镜像。
- 在VxWorks Shell中加载模块(若为可加载模块):
ld < task_preempt_demo.out - 调用入口函数:
taskPreemptDemo()
验证方法与判定标准
运行后在Shell终端观察输出。由于高优先级任务(priority=100)数值更小、优先级更高,当两个任务都处于就绪态时,高优先级任务会先获得CPU。预期输出模式为:
[HIGH] Round 1
[LOW ] Round 1
[HIGH] Round 2
[LOW ] Round 2
[HIGH] Round 3
[LOW ] Round 3
[HIGH] Round 4
[LOW ] Round 4
[HIGH] Round 5
[LOW ] Round 5
通过条件:每一轮中[HIGH]均先于[LOW]打印。若出现连续两个[LOW]或[LOW]先于[HIGH]打印,则说明抢占未生效,需检查任务优先级设置或系统调度配置。
关键说明
- 两个任务均调用
taskDelay(10)主动让出CPU,使两个任务交替获得运行机会,便于观察调度顺序。 - VxWorks中优先级数值越小,优先级越高。本案例中100高于150。
- 若需验证抢占的即时性(非时间片轮转),可删除
taskDelay,此时高优先级任务将独占CPU,低优先级任务永远无法运行——这也是抢占调度的直接体现,但不利于观察交替输出,故本案例保留taskDelay以展示抢占顺序。