FreeRTOS 快速入门(六)之互斥量


一、互斥量

1、基本概念

互斥量又称互斥信号量(本质是信号量),是一种特殊的二值信号量,它和信号量不同的是,它支持互斥量所有权、递归访问以及防止优先级翻转的特性,用于实现对临界资源的独占式处理。 任意时刻互斥量的状态只有两种,开锁或闭锁。当互斥量被任务持有时,该互斥量处于闭锁状态,这个任务获得互斥量的所有权。当该任务释放这个互斥量时,该互斥量处于开锁状态,任务失去该互斥量的所有权。当一个任务持有互斥量时,其他任务将不能再对该互斥量进行开锁或持有。持有该互斥量的任务也能够再次获得这个锁而不被挂起,这就是递归访问,也就是递归互斥量的特性,这个特性与一般的信号量有很大的不同,在信号量中,由于已经不存在可用的信号量,任务递归获取信号量时会发生主动挂起任务最终形成死锁。

如果想要用于实现同步(任务之间或者任务与中断之间),二值信号量或许是更好的选择,虽然互斥量也可以用于任务与任务、任务与中断的同步,但是互斥量更多的是用于保护资源的互锁。

互斥锁可以被视为一个与正在共享的资源相关联的令牌,对于合法访问资源的任务,它必须首先成功 “获取” 令牌,成为资源的持有者,当持有者完成对资源的访问之后,其需要 ”归还” 令牌,只有 “归还” 令牌之后,该令牌才可以再次被其他任务所 “获取” ,这样保证了互斥的对共享资源的访问,上述机制如下图所示:

2、运作机制

用互斥量处理不同任务对临界资源的同步访问时,任务想要获得互斥量才能进行资源访问,如果一旦有任务成功获得了互斥量,则互斥量立即变为闭锁状态,此时其他任务会因为获取不到互斥量而不能访问这个资源,任务会根据用户自定义的等待时间进行等待,直到互斥量被持有的任务释放后,其他任务才能获取互斥量从而得以访问该临界资源,此时互斥量再次上锁,如此一来就可以确保每个时刻只有一个任务正在访问这个临界资源,保证了临界资源操作的安全性。

3、死锁现象

“死锁” 是使用互斥锁进行互斥的另一个潜在陷阱,当两个任务因为都在等待对方占用的资源而无法继续进行时,就会发生死锁,考虑如下所述的情况:

  • 任务 A 执行并成功获取互斥量 X
  • 任务 A 被任务 B 抢占
  • 任务 B 在尝试获取互斥量 X 之前成功获取互斥量 Y,但互斥量 X 由任务 A 持有,因此对任务 B 不可用,任务 B 选择进入阻塞状态等待互斥量 X 被释放
  • 任务 A 继续执行,它尝试获取互斥量 Y,但互斥量 Y 由任务 B 持有,所以对于任务 A 来说是不可用的,任务 A 选择进入阻塞状态等待待释放的互斥量 Y

经过上述的这样一个过程,读者可以发现任务 A 在等待任务 B 释放互斥量 Y ,而任务 B 在等待任务 A 释放互斥量 X ,两个任务都在阻塞状态无法执行,从而导致 ”死锁“ 现象的发生,与优先级翻转一样,避免 “死锁” 的最佳方法是在设计时考虑其潜在影响,并设计系统以确保不会发生死锁。

4、递归互斥量

任务也有可能与自身发生死锁,如果任务尝试多次获取相同的互斥体而不首先返回互斥体,就会发生这种情况,考虑以下设想:

  • 任务成功获取互斥锁
  • 在持有互斥体的同时,任务调用库函数
  • 库函数的实现尝试获取相同的互斥锁,并进入阻塞状态等待互斥锁变得可用

在此场景结束时,任务处于阻塞

### FreeRTOS 快速入门指南教程 FreeRTOS 是一款开源的实时操作系统RTOS),专为嵌入式系统设计。它提供了一组 API 和软件库,帮助开发者实现任务管理、内存管理、中断处理、时间管理等功能,从而开发出高可靠性的实时嵌入式应用程序。为了快速入门并开始使用 FreeRTOS,以下是一些关键步骤和指导。 #### 安装和配置 FreeRTOS 1. **获取 FreeRTOS 源代码** FreeRTOS 的源代码可以从其官方网站下载。下载后,将源代码解压到您的项目目录中。通常,FreeRTOS 的源代码包含多个目录,其中 `FreeRTOS/Source` 目录下包含了核心的 RTOS 源文件,而 `FreeRTOS/Source/include` 目录下包含了头文件 [^3]。 2. **选择开发环境和目标平台** FreeRTOS 支持多种开发环境和目标平台,包括但不限于 ARM Cortex-M 系列、ESP32、AVR、PIC 等。根据您的目标平台选择合适的开发工具链,例如 Keil、IAR、GCC 等。 3. **配置 FreeRTOS** 在 `FreeRTOS/Source/include` 目录下有一个名为 `FreeRTOSConfig.h` 的配置文件。该文件定义了 FreeRTOS 的一些基本配置,例如系统时钟频率、任务调度策略、内存分配方式等。根据您的项目需求调整这些配置 [^2]。 #### 创建任务和调度 1. **创建任务** FreeRTOS 的任务是通过 `xTaskCreate()` 函数创建的。该函数需要传入任务函数、任务名称、堆栈大小、任务参数、任务优先级以及任务句柄等参数。例如: ```c void vTaskFunction(void *pvParameters) { for (;;) { // 任务执行的代码 vTaskDelay(pdMS_TO_TICKS(1000)); // 廷迟 1 秒 } } xTaskCreate(vTaskFunction, "Task1", 200, NULL, 1, NULL); ``` 2. **启动调度器** 在所有任务创建完成后,调用 `vTaskStartScheduler()` 启动调度器。此时,FreeRTOS 将开始调度任务的执行 。 #### 同步与通信机制 FreeRTOS 提供了多种同步与通信机制,例如信号(Semaphore)、互斥锁(Mutex)、队列(Queue)等。这些机制可以用于任务之间的同步和数据交换。 1. **信号** 信号可以通过 `xSemaphoreCreateBinary()` 创建,通过 `xSemaphoreTake()` 和 `xSemaphoreGive()` 进行获取和释放操作。 2. **队列** 队列可以通过 `xQueueCreate()` 创建,并通过 `xQueueSend()` 和 `xQueueReceive()` 进行发送和接收数据。 #### 内存管理 FreeRTOS 提供了多种内存分配策略,开发者可以根据项目需求选择合适的内存管理方式。默认情况下,FreeRTOS 使用静态内存分配,但也可以通过修改 `FreeRTOSConfig.h` 文件中的 `configUSE_MALLOC_LOCK_AND_RELEASE` 配置项来启用动态内存分配 [^2]。 #### 调试与优化 1. **调试工具** FreeRTOS 支持多种调试工具,例如 Tracealyzer、Percepio DevTools 等。这些工具可以帮助开发者分析任务调度、内存使用、中断响应等关键信息。 2. **性能优化** 通过调整任务优先级、优化任务调度策略、减少任务切换次数等方式,可以提高系统的实时性和性能。 #### 进一步学习 为了更深入地了解 FreeRTOS 的高级功能,建议阅读官方文档和相关教程。官方文档提供了详细的 API 说明和示例代码,帮助开发者更好地理解和使用 FreeRTOS [^1]。 --- ###
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值