4. 信号量获取释放延迟优化

任务目标

在VxWorks实时系统中,信号量获取/释放延迟直接影响任务响应时间。本案例完成两件事:测量二进制信号量与互斥信号量的获取释放延迟(使用clock_gettime获取纳秒级时间戳),并通过缩小临界区范围优化延迟。

环境依赖

  • VxWorks 7或6.9+,支持POSIX时钟接口
  • 包含semLib.h、time.h、taskLib.h

关键完整代码

/* sem_latency_demo.c */
#include <vxWorks.h>
#include <semLib.h>
#include <time.h>
#include <taskLib.h>
#include <stdio.h>

#define ITERATIONS 1000

/* 模拟临界区工作负载:简单计算 */
static void do_work(int workload) {
    volatile int sum = 0;
    for (int i = 0; i < workload; i++) {
        sum += i;
    }
}

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

/* 测量信号量获取/释放延迟 */
static void measure_sem(SEM_ID sem, const char *name, int workload) {
    UINT64 start, end, total = 0;
    int i;

    for (i = 0; i < ITERATIONS; i++) {
        start = get_ns();
        semTake(sem, WAIT_FOREVER);
        do_work(workload);  /* 临界区内工作 */
        semGive(sem);
        end = get_ns();
        total += (end - start);
    }
    printf("%s (workload=%d): avg latency = %llu ns\n",
           name, workload, (unsigned long long)(total / ITERATIONS));
}

/* 优化前:临界区内包含不必要的工作 */
static void unoptimized(SEM_ID bin_sem, SEM_ID mutex_sem) {
    measure_sem(bin_sem, "binary unoptimized", 100);
    measure_sem(mutex_sem, "mutex unoptimized", 100);
}

/* 优化后:仅将必要共享资源保护在临界区内 */
static void optimized(SEM_ID bin_sem, SEM_ID mutex_sem) {
    measure_sem(bin_sem, "binary optimized", 10);
    measure_sem(mutex_sem, "mutex optimized", 10);
}

void sem_latency_demo(void) {
    SEM_ID bin_sem, mutex_sem;

    /* 创建信号量 */
    bin_sem = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
    mutex_sem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);

    if (bin_sem == NULL || mutex_sem == NULL) {
        printf("Semaphore creation failed\n");
        return;
    }

    printf("--- Semaphore Latency Measurement ---\n");
    unoptimized(bin_sem, mutex_sem);
    optimized(bin_sem, mutex_sem);

    /* 清理 */
    semDelete(bin_sem);
    semDelete(mutex_sem);
}

运行与验证

  1. 将代码编译链接到VxWorks镜像或作为可下载模块加载:
    cc -c sem_latency_demo.c -o sem_latency_demo.o
    ld -r sem_latency_demo.o -o sem_latency_demo.out
  2. 在VxWorks shell中调用:sem_latency_demo
  3. 通过判定标准:程序正常输出4行延迟数据;优化后(workload=10)的平均延迟应明显低于优化前(workload=100)——因为临界区执行时间缩短,阻塞时间减少。若系统负载稳定,多次运行结果应具有可重复性。

关键说明

  • 本案例通过缩小临界区内工作量(从100次循环降至10次)模拟优化,实际项目中应将非共享资源操作移出临界区。
  • 互斥信号量启用SEM_INVERSION_SAFE(优先级继承),在优先级反转场景下延迟特性与二进制信号量不同。
  • 测量包含semTake/semGive系统调用开销及任务调度时间,反映真实获取释放延迟。
  • 若需更精确测量,可关闭中断或使用taskLock,但会改变实时行为,本案例保持真实运行环境。