FreeRTOS 中互斥锁的使用

互斥锁的概念

        互斥锁(Mutex,全名Mutual Exclusion)是一种用于控制多个线程对共享资源访问的同步机制。在并发编程中,多个线程同时访问共享资源可能导致数据不一致性或竞态条件(Race Condition)。为了避免这种情况,可以使用互斥锁来确保在任意时刻只有一个线程能够访问共享资源。

        互斥锁的基本原理是,当一个线程想要访问共享资源时,它必须先尝试获取互斥锁。如果该锁已经被其他线程持有,那么请求线程就会被阻塞,直到锁被释放。一旦线程成功获取了互斥锁,它就可以安全地访问共享资源,完成操作后再释放锁,以便其他线程可以继续访问。

        在不同的编程语言和操作系统中,互斥锁的实现方式可能会有所不同,但基本的思想是一致的。使用互斥锁可以有效地防止多个线程同时修改共享数据,从而确保线程安全性。

        需要注意的是,虽然互斥锁能够解决竞态条件问题,但过度使用锁可能导致性能问题,因为锁的获取和释放会引入额外的开销。因此,在设计并发程序时,需要谨慎考虑锁的使用,以在安全性和性能之间找到平衡。

FreeRTOS的互斥锁

        FreeRTOS 是一款用于嵌入式系统的实时操作系统(RTOS)。FreeRTOS 提供了一些同步机制,其中包括用于保护共享资源的互斥锁。在 FreeRTOS 中,互斥锁称为二进制信号量,通过 Semaphore 数据结构实现。

        以下是 FreeRTOS 中互斥锁的基本使用方法:

1. 引入头文件

        在使用互斥锁之前,需要引入 FreeRTOS 的头文件。

#include "FreeRTOS.h"

#include "semphr.h"

2. 创建互斥锁

        使用 xSemaphoreCreateMutex() 函数创建一个互斥锁。这个函数返回一个指向互斥锁的句柄。

SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();

3. 获取互斥锁(加锁)

        在访问共享资源之前,需要获取互斥锁。使用 xSemaphoreTake() 函数来尝试获取锁。

if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {

    // 访问共享资源的代码

    // ...

}

        portMAX_DELAY 表示无限等待,直到成功获取锁。

4. 释放互斥锁(解锁)

        在访问共享资源后,需要释放互斥锁,以便其他任务可以获取锁。

xSemaphoreGive(xMutex);

        通过调用 xSemaphoreGive() 来释放互斥锁。

        在以上的代码片段中,xMutex 是互斥锁的句柄,xSemaphoreTake() 用于获取锁,xSemaphoreGive() 用于释放锁。在实时系统中,这样的互斥锁机制有助于确保共享资源的线程安全性。

        请注意,FreeRTOS 还提供其他类型的信号量,如计数信号量,可以用于更灵活的同步操作。在使用 FreeRTOS 时,建议查阅官方文档和示例代码,以确保正确地使用互斥锁和其他同步机制。

STM32F103案例

        创建一个互斥锁,然后有两个任务,每个任务都会尝试获取互斥锁,然后对共享资源进行访问。

        请确保已经配置好 STM32CubeMX 和相关的开发环境,同时已经集成了 FreeRTOS。

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "stm32f1xx_hal.h"

// 互斥锁句柄
SemaphoreHandle_t xMutex;
// 共享资源
volatile uint32_t sharedResource = 0;

void Task1(void *pvParameters) {
    while (1) {
        // 尝试获取互斥锁
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 访问共享资源
            sharedResource++;
            // 释放互斥锁
            xSemaphoreGive(xMutex);
        }
        vTaskDelay(pdMS_TO_TICKS(1000));  // 任务延时1秒
    }
}

void Task2(void *pvParameters) {
    while (1) {
        // 尝试获取互斥锁
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 访问共享资源
            sharedResource--;
            // 释放互斥锁
            xSemaphoreGive(xMutex);
        }
        vTaskDelay(pdMS_TO_TICKS(500));  // 任务延时500毫秒
    }
}

int main(void) {
    // 初始化 FreeRTOS
    HAL_Init();
    SystemClock_Config();

    // 创建互斥锁
    xMutex = xSemaphoreCreateMutex();

    // 创建任务
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

    // 启动调度器
    vTaskStartScheduler();
    // 程序不应该执行到这里
    while (1) {

    }

}

        在这个例子中,使用 xMutex 作为互斥锁的句柄,两个任务 Task1 和 Task2 分别尝试获取互斥锁,对共享资源进行读写,并在操作后释放互斥锁。 vTaskDelay 函数用于模拟任务的执行时间。

        请注意,这只是一个简单的示例,实际的应用可能需要更多的复杂性和保护来确保线程安全。此外,确保在 STM32CubeMX 中正确配置 FreeRTOS,包括堆栈和任务优先级等。在实际应用中,你可能需要添加更多的任务和功能,以满足特定的需求。

        关于CubeMX的配置请看我以前更新的博客

猜你喜欢

转载自blog.csdn.net/m0_56694518/article/details/134897059