跳过正文

VxWorks 7信号量简介

VxWorks 7
目录
app - 这篇文章属于一个选集。
§ 10: 本文

VxWorks 7 信号量概述
#

在实时操作系统(RTOS)中,信号量是一种重要的同步机制,用于管理多任务环境下的资源访问和任务同步。VxWorks 7提供了多种类型的信号量来满足不同的应用场景需求,主要包括:

  • 互斥信号量(Mutex Semaphores):确保对共享资源的互斥访问。
  • 二进制信号量(Binary Semaphores):类似于互斥信号量,但更简单,常用于任务同步。
  • 计数信号量(Counting Semaphores):可以计数,可以表示多个资源的可用性。

信号量的基本操作
#

  1. 创建信号量:
  • semMCreate 创建互斥信号量。
  • semBCreate 创建二进制信号量。
  • semCCreate 创建计数信号量。
  1. 获取信号量:
  • semTake 阻塞模式下获取信号量。
  • semTakeWithTimeout 带有超时功能的获取信号量。
  1. 释放信号量:
  • semGive 释放信号量。
  1. 删除信号量:
  • semDelete 删除信号量。

代码示例
#

创建并使用互斥信号量
#

#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>

/* 互斥信号量的句柄 */
SEM_ID mutexSem;

void task1(void)
{
    while (1)
    {
        /* 获取互斥信号量 */
        if (semTake(mutexSem, WAIT_FOREVER) == OK)
        {
            printf("Task1: Got the mutex\n");
            
            /* 临界区的代码 */
            /* 例如,修改共享资源 */
            
            /* 释放互斥信号量 */
            semGive(mutexSem);
            taskDelay(100); // 延时以模拟任务执行
        }
    }
}

void task2(void)
{
    while (1)
    {
        /* 获取互斥信号量 */
        if (semTake(mutexSem, WAIT_FOREVER) == OK)
        {
            printf("Task2: Got the mutex\n");
            
            /* 临界区的代码 */
            /* 例如,访问共享资源 */
            
            /* 释放互斥信号量 */
            semGive(mutexSem);
            taskDelay(100); // 延时以模拟任务执行
        }
    }
}

int main()
{
    /* 创建互斥信号量 */
    mutexSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
    if (mutexSem == NULL)
    {
        printf("Failed to create mutex semaphore\n");
        return ERROR;
    }

    /* 创建任务 */
    if (taskSpawn("t1", 100, 0, 4000, (FUNCPTR)task1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
    {
        printf("Failed to spawn task1\n");
        return ERROR;
    }
    if (taskSpawn("t2", 100, 0, 4000, (FUNCPTR)task2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
    {
        printf("Failed to spawn task2\n");
        return ERROR;
    }

    return 0;
}

错误处理
#

为了严谨,上述代码需要添加相关的错误处理,如下:

#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
#include <errnoLib.h>

/* 互斥信号量的句柄 */
SEM_ID mutexSem;

void task1(void)
{
    STATUS status;
    while (1)
    {
        /* 获取互斥信号量 */
        status = semTake(mutexSem, WAIT_FOREVER);
        if (status != OK)
        {
            printf("Task1: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
        }
        else
        {
            printf("Task1: Got the mutex\n");
            
            /* 临界区的代码 */
            /* 例如,修改共享资源 */
            
            /* 释放互斥信号量 */
            status = semGive(mutexSem);
            if (status != OK)
            {
                printf("Task1: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
            }
            taskDelay(100); // 延时以模拟任务执行
        }
    }
}

void task2(void)
{
    STATUS status;
    while (1)
    {
        /* 获取互斥信号量 */
        status = semTake(mutexSem, WAIT_FOREVER);
        if (status != OK)
        {
            printf("Task2: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
        }
        else
        {
            printf("Task2: Got the mutex\n");
            
            /* 临界区的代码 */
            /* 例如,访问共享资源 */
            
            /* 释放互斥信号量 */
            status = semGive(mutexSem);
            if (status != OK)
            {
                printf("Task2: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
            }
            taskDelay(100); // 延时以模拟任务执行
        }
    }
}

int main()
{
    STATUS status;

    /* 创建互斥信号量 */
    mutexSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
    if (mutexSem == NULL)
    {
        printf("Failed to create mutex semaphore. Error: %s\n", strerror(errnoGet()));
        return ERROR;
    }

    /* 创建任务 */
    status = taskSpawn("t1", 100, 0, 4000, (FUNCPTR)task1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    if (status == ERROR)
    {
        printf("Failed to spawn task1. Error: %s\n", strerror(errnoGet()));
        return ERROR;
    }

    status = taskSpawn("t2", 100, 0, 4000, (FUNCPTR)task2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    if (status == ERROR)
    {
        printf("Failed to spawn task2. Error: %s\n", strerror(errnoGet()));
        return ERROR;
    }

    return 0;
}

错误处理的说明:

  • semTake 和 semGive 函数的返回值被检查,如果返回值不是 OK,则表示操作失败,此时会打印错误信息。
  • 使用 errnoGet() 函数获取错误码,并通过 strerror() 将错误码转换为可读的错误信息。
  • 对于信号量的创建和任务的生成,同样检查返回值,保证操作成功,不成功时提供相应的错误信息。
  • 这样做可以帮助你更容易地诊断和修复程序中的问题,尤其是在信号量操作或任务管理方面。

超时处理
#

#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
#include <errnoLib.h>

/* 互斥信号量的句柄 */
SEM_ID mutexSem;

/* 超时时间定义,单位为ticks */
#define SEM_TIMEOUT   100

void task1(void)
{
    STATUS status;
    while (1)
    {
        /* 获取互斥信号量,带超时处理 */
        status = semTake(mutexSem, SEM_TIMEOUT);
        if (status != OK)
        {
            if (status == ERROR)
            {
                printf("Task1: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
            }
            else if (status == S_objLib_OBJ_TIMEOUT)
            {
                printf("Task1: Timed out waiting for semaphore.\n");
            }
        }
        else
        {
            printf("Task1: Got the mutex\n");
            
            /* 临界区的代码 */
            /* 例如,修改共享资源 */
            
            /* 释放互斥信号量 */
            status = semGive(mutexSem);
            if (status != OK)
            {
                printf("Task1: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
            }
            taskDelay(100); // 延时以模拟任务执行
        }
    }
}

void task2(void)
{
    STATUS status;
    while (1)
    {
        /* 获取互斥信号量,带超时处理 */
        status = semTake(mutexSem, SEM_TIMEOUT);
        if (status != OK)
        {
            if (status == ERROR)
            {
                printf("Task2: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
            }
            else if (status == S_objLib_OBJ_TIMEOUT)
            {
                printf("Task2: Timed out waiting for semaphore.\n");
            }
        }
        else
        {
            printf("Task2: Got the mutex\n");
            
            /* 临界区的代码 */
            /* 例如,访问共享资源 */
            
            /* 释放互斥信号量 */
            status = semGive(mutexSem);
            if (status != OK)
            {
                printf("Task2: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
            }
            taskDelay(100); // 延时以模拟任务执行
        }
    }
}

int main()
{
    STATUS status;

    /* 创建互斥信号量 */
    mutexSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
    if (mutexSem == NULL)
    {
        printf("Failed to create mutex semaphore. Error: %s\n", strerror(errnoGet()));
        return ERROR;
    }

    /* 创建任务 */
    status = taskSpawn("t1", 100, 0, 4000, (FUNCPTR)task1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    if (status == ERROR)
    {
        printf("Failed to spawn task1. Error: %s\n", strerror(errnoGet()));
        return ERROR;
    }

    status = taskSpawn("t2", 100, 0, 4000, (FUNCPTR)task2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    if (status == ERROR)
    {
        printf("Failed to spawn task2. Error: %s\n", strerror(errnoGet()));
        return ERROR;
    }

    return 0;
}

超时处理的说明:

  • 在调用 semTake 时,第二个参数不再是 WAIT_FOREVER,而是使用了 SEM_TIMEOUT 来设置超时时间。
  • 如果在指定时间内未获取到信号量,semTake 会返回 S_objLib_OBJ_TIMEOUT,此时可以通知任务超时。
  • 这种方式可以防止任务因等待信号量而被无限期阻塞,特别有用在需要实时响应的系统中。

注意事项
#

  • 信号量必须在使用前创建,并且在不再需要时删除以释放资源。
  • 长时间持有信号量可能会导致优先级反转问题,VxWorks提供了优先级继承来解决这个问题。
  • 使用信号量时要考虑任务的优先级和实时性要求,以避免死锁等问题。

这个示例展示了如何在VxWorks 7中使用互斥信号量来协调两个任务对共享资源的访问。实际应用中,你可能需要根据具体需求选择不同的信号量类型,并考虑性能与资源利用的平衡。

app - 这篇文章属于一个选集。
§ 10: 本文

相关文章

VxWorks 7开发用户指南
VxWorks 7
VxWorks 7.0 中文教程
VxWorks 7 Development Tutorial
U-Boot和VxWorks 7的集成
VxWorks 7 U-Boot