1. 任务创建与删除开销分析

任务说明

本案例目标是在 VxWorks 环境中测量任务创建(taskSpawn)与删除(taskDelete)的时间开销,并分析影响开销的关键因素。测量结果用于指导实时系统设计中的任务生命周期管理策略。

环境依赖

  • VxWorks 6.9+ 或 7.x 开发环境
  • 目标机或风河模拟器(VxSim)
  • 包含 timestamp 高精度计时驱动(或使用 clock_gettime 替代)

实现思路

使用系统高精度时间戳在任务创建前后分别取点,计算差值;删除操作在任务自身中执行,同样记录时间戳。为消除单次测量抖动,循环执行多次并统计平均值与最大值。关键分析维度包括:任务栈大小、任务优先级、系统当前任务数对创建/删除开销的影响。

关键完整代码

/* task_overhead.c - 任务创建与删除开销测量 */
#include <vxWorks.h>
#include <taskLib.h>
#include <timers.h>
#include <stdio.h>

#define MAX_ITER  1000
#define STACK_SIZE 8192

static UINT64 taskStartTime;
static UINT64 taskEndTime;
static UINT64 createTotal = 0;
static UINT64 deleteTotal = 0;
static UINT64 createMax = 0;
static UINT64 deleteMax = 0;
static int iterCount = 0;

/* 获取纳秒级时间戳 */
static UINT64 getNanoTime(void)
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (UINT64)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}

/* 被创建的任务:记录删除时间并自杀 */
static void workerTask(void)
{
    taskEndTime = getNanoTime();
    taskDelete(0);  /* 删除自身 */
}

/* 执行一轮创建+删除测量 */
static void measureOnce(int prio, int stackSize)
{
    UINT64 t0, t1, createCost, deleteCost;
    int tid;

    t0 = getNanoTime();
    tid = taskSpawn("tWorker", prio, 0, stackSize,
                    (FUNCPTR)workerTask, 0,0,0,0,0,0,0,0,0);
    t1 = getNanoTime();
    if (tid == ERROR) {
        printf("taskSpawn failed\n");
        return;
    }

    createCost = t1 - t0;
    /* 等待任务完成删除 */
    while (taskIdVerify(tid) == OK) {
        taskDelay(1);
    }
    deleteCost = taskEndTime - taskStartTime;

    createTotal += createCost;
    deleteTotal += deleteCost;
    if (createCost > createMax) createMax = createCost;
    if (deleteCost > deleteMax) deleteMax = deleteCost;
    iterCount++;
}

/* 测量入口 */
void measureTaskOverhead(void)
{
    int i;
    int prio = 100;
    int stack = STACK_SIZE;

    printf("=== Task Create/Delete Overhead (ns) ===\n");

    /* 场景1:默认优先级与栈大小 */
    iterCount = 0;
    createTotal = deleteTotal = 0;
    createMax = deleteMax = 0;
    for (i = 0; i < MAX_ITER; i++) {
        taskStartTime = getNanoTime();
        measureOnce(prio, stack);
    }
    printf("Default prio=%d stack=%d\n", prio, stack);
    printf("  Create avg=%llu max=%llu\n",
           createTotal / iterCount, createMax);
    printf("  Delete avg=%llu max=%llu\n",
           deleteTotal / iterCount, deleteMax);

    /* 场景2:高优先级 */
    iterCount = 0;
    createTotal = deleteTotal = 0;
    createMax = deleteMax = 0;
    for (i = 0; i < MAX_ITER; i++) {
        taskStartTime = getNanoTime();
        measureOnce(50, stack);
    }
    printf("High prio=%d stack=%d\n", 50, stack);
    printf("  Create avg=%llu max=%llu\n",
           createTotal / iterCount, createMax);
    printf("  Delete avg=%llu max=%llu\n",
           deleteTotal / iterCount, deleteMax);

    /* 场景3:大栈 */
    iterCount = 0;
    createTotal = deleteTotal = 0;
    createMax = deleteMax = 0;
    for (i = 0; i < MAX_ITER; i++) {
        taskStartTime = getNanoTime();
        measureOnce(prio, 65536);
    }
    printf("Large stack prio=%d stack=65536\n", prio);
    printf("  Create avg=%llu max=%llu\n",
           createTotal / iterCount, createMax);
    printf("  Delete avg=%llu max=%llu\n",
           deleteTotal / iterCount, deleteMax);
}

编译与运行

# 在 VxWorks 开发环境中编译(以命令行为例)
ccpentium -c task_overhead.c -o task_overhead.o
# 链接到 VxWorks 镜像或作为动态加载模块

# 在目标机 shell 中运行
-> measureTaskOverhead

验证方法

  • 程序正常输出三组场景的创建/删除平均耗时与最大耗时,数值单位为纳秒。
  • 观察输出中高优先级任务(50)与默认优先级(100)的创建耗时差异,通常高优先级创建略慢(内核需插入更高优先级就绪队列)。
  • 大栈(65536)场景的创建耗时应明显高于小栈(8192),反映内存分配与初始化成本。
  • 删除耗时通常小于创建耗时,且受栈大小影响较小——删除主要释放 TCB 与内核资源,栈释放为整体操作。

预期输出示例

=== Task Create/Delete Overhead (ns) ===
Default prio=100 stack=8192
  Create avg=4520 max=7830
  Delete avg=3180 max=5420
High prio=50 stack=8192
  Create avg=4890 max=8210
  Delete avg=3220 max=5610
Large stack prio=100 stack=65536
  Create avg=12450 max=18900
  Delete avg=3350 max=5780

以上数值仅为逻辑一致的示例,实际数值取决于目标机 CPU 频率、内存速度与 VxWorks 内核配置。

关键因素分析

  • 栈大小:创建时需分配并可能清零栈内存,是创建开销的主要变量。
  • 优先级:影响就绪队列插入操作,高优先级插入可能触发更复杂的调度器路径。
  • 系统负载:当前活动任务数影响内核链表操作与缓存命中率。
  • 删除操作:主要固定成本在 TCB 释放与资源回收,与栈大小弱相关。