【Freertos基础入门】深入浅出freertos互斥量

简介: 【Freertos基础入门】深入浅出freertos互斥量

前言


FreeRTOS是一款开源的实时操作系统,提供了许多基本的内核对象,其中包括互斥锁(Mutex)。互斥锁是一种常用的同步机制,用于确保在同一时间内只有一个任务可以访问共享资源,防止竞态条件等并发问题。本文将介绍FreeRTOS中的互斥锁的使用方法和注意事项。


一、互斥量是什么?


当多个任务同时操作一个共享资源时,就可能出现竞态条件(Race Condition)的问题,导致数据错乱或不一致的情况。为了解决这个问题,FreeRTOS提供了互斥量(Mutex)的概念。


可以将互斥量类比为一把锁,只有拿到这把锁的任务才能操作共享资源,其他任务需要等待。互斥量的作用是保护共享资源,确保在同一时间内只有一个任务可以访问它。


具体来说,当一个任务需要访问共享资源时,它首先要尝试获取互斥量。如果互斥量没有被其他任务占用,那么这个任务就可以获得互斥量,相当于拿到了锁,并且可以继续执行。而如果互斥量已经被其他任务占用,那么这个任务就会被阻塞,等待互斥量可用。


一旦任务完成了对共享资源的操作,它需要释放互斥量,相当于释放了锁,这样其他任务就有机会获取互斥量,继续执行对共享资源的操作。


互斥量还支持嵌套,即一个任务在持有互斥量时,可以再次尝试获取互斥量。这样可以在多个层次上获取和释放互斥量,确保资源的正确使用。但要注意,在释放互斥量之前,必须相同次数地释放它,否则会导致其他任务无法获取到互斥量,可能导致死锁问题。


当谈到互斥量,一个生活化的比喻可以是门锁。


想象一下,你和其他人住在同一栋公寓楼里,每个人都有自己的房间。这些房间是共享资源,大家都会使用公共的厨房。现在,你正在做晚餐,需要使用炉灶和炒锅。由于只有一个炉灶和炒锅可供使用,你就安装了一个门锁来保护炉灶和炒锅,让其他人知道你正在使用它们。


在这个比喻中,互斥量就好像是这个门锁。只有先到达的人可以拥有锁的使用权,其他人需要等待锁被释放才能使用炉灶和炒锅。这样做的好处是,可以确保一次只有一个人使用炉灶和炒锅,避免混乱和争夺,同时保证了大家能有有序地使用共享资源的机会。


类似地,FreeRTOS中的互斥量可用于保护共享资源,只有一个任务可以获取互斥量的使用权,其他任务需要等待互斥量释放才能访问共享资源。这种机制保护了共享资源的完整性,避免了并发访问可能导致的竞态条件和数据不一致性问题。


希望这个比喻能够让互斥量的概念更加具体和易于理解。


总之,互斥量是FreeRTOS提供的一种同步机制,用于确保在同一时间内只有一个任务可以访问共享资源,避免了竞态条件的问题。它就像一把锁,任务需要获取锁才能操作共享资源,其他任务需要等待。通过合理使用互斥量,可以保证系统数据的一致性和正确性。


二、互斥量的使用场景


FreeRTOS的互斥量(Mutex)是一种非常有用的同步机制,用于保护共享资源、避免竞态条件和确保数据的一致性。下面是一些常见的使用场景:


共享资源保护: 当多个任务需要同时访问共享资源(如全局变量、设备IO等)时,互斥量可以用于保护这些资源,以确保在同一时间内只有一个任务可以访问。其他任务必须等待互斥量可用时才能进行访问,从而避免竞态条件和数据不一致性。


任务间通信: 互斥量可以用于任务间的通信和同步。例如,一个任务负责生成数据,另一个任务负责处理数据。生成数据的任务可以在生成后使用互斥量释放锁,通知处理数据的任务可以获取锁,开始处理数据。这种方式可以实现任务间的协作和同步。


资源分配与释放: 当有多个任务需要访问有限的资源时,互斥量可以用于分配和释放资源。例如,一块只能同时由一个任务访问的内存区域,可以使用互斥量来管理访问权限。任务需要访问内存时,首先尝试获取互斥量,成功获取则可以访问内存,否则需要等待。


临界区保护: 互斥量可以用于保护临界区,即一段关键的代码,确保在同一时间内只有一个任务可以执行该代码段。这对于需要保护关键数据或临界资源的操作非常重要,以确保数据的完整性和正确性。


任务优先级反转解决方案: 在任务优先级反转的情况下,互斥量可以用于解决该问题。任务优先级反转是指高优先级任务被低优先级任务所阻塞的情况,可能导致系统性能下降。通过使用互斥量,高优先级任务可以在访问共享资源之前阻塞低优先级任务,从而避免任务优先级反转。


这些是FreeRTOS互斥量的常见使用场景,通过合理地应用互斥量,可以保护共享资源、实现任务间的同步和协作,确保数据的一致性和系统的正确性。


三、互斥量的使用


互斥量其实就是一种特殊的二进制信号量。


1.创建

使用互斥量时,先创建、然后去获得、释放它。使用句柄来表示一个互斥量。

创建互斥量的函数有2种:动态分配内存,静态分配内存,函数原型如下:

/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );
/* 创建一个互斥量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer
);


要想使用互斥量,需要在配置文件FreeRTOSConfig.h中定义:

#define configUSE_MUTEXES 1


比如下图步骤:

1、搜索文件

2b993ad7f02f4d03ae0dd2823500d01f.png

2、开启互斥量

a75368c2bd8d405cb515f67088ce6151.png


2.删除互斥量


使用vSemaphoreDelete删除互斥量

/*
* xSemaphore: 信号量句柄,你要删除哪个信号量, 互斥量也是一种信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore )


3.give和take


他们的参数和我们的信号量差不多,所以我在这就不写了。

give函数原型如下:

/* 释放 */
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );


take函数原型如下:

/* 获得 */
BaseType_t xSemaphoreTake(
SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait
);


要注意的是,互斥量不能在ISR中使用。


四、示例代码

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
// 共享资源
int sharedResource = 0;
// 互斥量句柄
SemaphoreHandle_t mutex;
// 任务函数1
void Task1(void *pvParameters)
{
    while (1)
    {
        // 获取互斥量
        xSemaphoreTake(mutex, portMAX_DELAY);
        // 在临界区内对共享资源进行操作
        sharedResource++;
        printf("Task1: sharedResource = %d\n", sharedResource);
        // 释放互斥量
        xSemaphoreGive(mutex);
        // 等待一段时间
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
// 任务函数2
void Task2(void *pvParameters)
{
    while (1)
    {
        // 获取互斥量
        xSemaphoreTake(mutex, portMAX_DELAY);
        // 在临界区内对共享资源进行操作
        sharedResource--;
        printf("Task2: sharedResource = %d\n", sharedResource);
        // 释放互斥量
        xSemaphoreGive(mutex);
        // 等待一段时间
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
int main(void)
{
    // 创建互斥量
    mutex = xSemaphoreCreateMutex();
    // 创建任务
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
    xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
    // 启动调度器
    vTaskStartScheduler();
    // 如果启动成功,将不会执行到这里
    while(1);
}


在串口中我们就可以看到打印出来的东西了。


总结


互斥锁是FreeRTOS提供的一个重要的同步机制,用于控制对共享资源的访问。通过仔细使用互斥锁,可以防止并发问题如竞态条件、死锁等的发生。本文简要介绍了在FreeRTOS中使用互斥锁的基本方法,包括创建、获取、释放和处理错误。在实际应用中,需要根据具体的场景和需求来合理使用互斥锁,确保系统的正确性和性能。

相关文章
|
10月前
|
API
FreeRTOS学习笔记—FreeRTOS移植
本文学习了如何移植FreeRTOS到自己的STM32工程。最后,根据正点原子提供的测试main函数,测试了移植效果。
277 0
FreeRTOS学习笔记—FreeRTOS移植
|
10月前
|
传感器 调度 开发者
【Freertos基础入门】freertos任务的优先级
【Freertos基础入门】freertos任务的优先级
319 0
|
2月前
|
消息中间件 算法 编译器
【FreeRTOS(一)】FreeRTOS新手入门——初识FreeRTOS
【FreeRTOS(一)】FreeRTOS新手入门——初识FreeRTOS
|
2月前
|
传感器 物联网 调度
从0入门FreeRTOS之第一节 什么是FreeRTOS?
FreeRTOS(Free Real-Time Operating System)是一款开源的实时操作系统(RTOS),专为嵌入式系统设计。由Real Time Engineers Ltd.开发和维护,FreeRTOS以其小巧、高效、易于使用的特点广受欢迎。FreeRTOS支持多种微控制器和微处理器平台,提供丰富的实时操作系统功能,使开发者能够轻松构建高效、实时响应的应用程序。
167 0
|
2月前
|
存储 安全 算法
从0入门FreeRTOS之第二节FreeRTOS的体系结构
FreeRTOS的体系结构设计精巧且高效,专为嵌入式系统量身打造。理解FreeRTOS的体系结构对开发高效、稳定的嵌入式应用至关重要。下面,我们详细介绍FreeRTOS的核心组件、内核机制、中断管理和内存管理等内容。
73 0
|
3月前
|
消息中间件 调度
FreeRTOS入门教程(任务状态)
FreeRTOS入门教程(任务状态)
138 0
|
10月前
|
调度 C语言 芯片
FreeRTOS学习笔记—基础知识
本文简要介绍了什么是RTOS,介绍了前后台系统和RTOS的工作流程。此外,简单介绍了FreeRTOS的特点,相关概念和优点。最后,介绍了下载FreeRTOS的方法。
201 0
FreeRTOS学习笔记—基础知识
|
10月前
|
调度 开发者
【Freertos基础入门】2个Freertos的Delay函数
【Freertos基础入门】2个Freertos的Delay函数
448 1
|
10月前
|
存储 消息中间件 API
FreeRTOS入门教程(堆和栈)
FreeRTOS入门教程(堆和栈)
278 0
|
3月前
FreeRTOS入门教程(信号量的具体使用)
FreeRTOS入门教程(信号量的具体使用)
88 0