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);
}

运行与验证

  1. 编译加载:在VxWorks开发环境中编译该文件生成task_suspend_resume.o,通过FTP或WindSh加载到目标机。
  2. 启动任务:在Shell中调用taskSuspendResumeStart()。
  3. 观察串口输出,预期时序如下:
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(...)手动验证,效果相同。
t 0s 1s 3s 6s Task A RUNNING (打印count) SUSPENDED RUNNING (继续) Task B 延时 taskSuspend 延时3s taskResume 退出 挂起 恢复 运行 挂起 延时 系统调用

上图展示了任务A与任务B在时间轴上的状态变化:任务A先运行约1秒后被任务B挂起,挂起持续3秒,恢复后继续运行;任务B在完成挂起/恢复操作后自行退出。