4. 任务挂起与恢复
任务挂起与恢复:taskSuspend / taskResume
本案例演示如何在VxWorks中通过taskSuspend()与taskResume()控制任务执行状态。核心目标是:创建两个任务,任务A周期性打印运行计数,任务B在延时后挂起任务A,再延时后恢复任务A,从而在串口终端观察到任务A的打印中断与恢复过程。
实现代码
/* task_suspend_resume.c - VxWorks任务挂起与恢复示例 */
#include <vxWorks.h>
#include <taskLib.h>
#include <stdio.h>
/* 任务A:周期性打印运行次数 */
static volatile int taskACount = 0;
static void taskA(void)
{
while (1)
{
printf("Task A running, count = %d\n", ++taskACount);
taskDelay(sysClkRateGet() / 2); /* 延时500ms */
}
}
/* 任务B:控制任务A的挂起与恢复 */
static void taskB(void)
{
TASK_ID tidA = taskNameToId("tTaskA");
if (tidA == ERROR)
{
printf("Error: task tTaskA not found\n");
return;
}
printf("Task B: suspending tTaskA...\n");
if (taskSuspend(tidA) == OK)
printf("Task B: tTaskA suspended\n");
else
printf("Task B: taskSuspend failed (errno=0x%x)\n", errnoGet());
taskDelay(sysClkRateGet() * 3); /* 保持挂起3秒 */
printf("Task B: resuming tTaskA...\n");
if (taskResume(tidA) == OK)
printf("Task B: tTaskA resumed\n");
else
printf("Task B: taskResume failed (errno=0x%x)\n", errnoGet());
/* 观察恢复后任务A继续运行,然后结束任务B */
taskDelay(sysClkRateGet() * 2);
printf("Task B: exiting\n");
taskDelete(0);
}
/* 启动入口:在shell中调用 */
void taskSuspendResumeStart(void)
{
taskSpawn("tTaskA", 100, 0, 2000, (FUNCPTR)taskA, 0,0,0,0,0,0,0,0,0,0);
taskSpawn("tTaskB", 101, 0, 2000, (FUNCPTR)taskB, 0,0,0,0,0,0,0,0,0,0);
}
运行与验证
- 编译加载:在VxWorks开发环境中编译该文件生成
task_suspend_resume.o,通过FTP或WindSh加载到目标机。 - 启动任务:在Shell中调用
taskSuspendResumeStart()。 - 观察串口输出,预期时序如下:
Task A running, count = 1
Task A running, count = 2
Task B: suspending tTaskA...
Task B: tTaskA suspended
Task B: resuming tTaskA...
Task B: tTaskA resumed
Task A running, count = 3
Task A running, count = 4
Task B: exiting
通过判定标准:
- 串口输出中出现
suspended后,任务A的count打印停止约3秒; - 出现
resumed后,任务A从count=3继续打印,说明任务恢复后从断点继续执行; - 任务B退出后,任务A持续运行(若需停止可手动
taskDelete(taskNameToId("tTaskA")))。
关键说明
taskSuspend()挂起指定任务,任务进入挂起态(SUSPEND),不参与调度;taskResume()使其回到就绪态。- 任务B通过
taskNameToId()获取任务A的ID,避免硬编码TID。 - 挂起期间任务A的
taskDelay()计时暂停,恢复后继续执行剩余延时,因此计数从3而非1继续。 - 若在Shell中直接操作,也可用
taskSuspend(taskNameToId("tTaskA"))和taskResume(...)手动验证,效果相同。
上图展示了任务A与任务B在时间轴上的状态变化:任务A先运行约1秒后被任务B挂起,挂起持续3秒,恢复后继续运行;任务B在完成挂起/恢复操作后自行退出。