zephyr笔记 2.4.2 互斥锁

本文详细介绍了Zephyr操作系统中的互斥锁概念及其实现方式,包括互斥锁的基本属性、可重入锁定、优先继承等核心知识点,并提供了定义、初始化、锁定和解锁互斥锁的具体操作示例。

1 前言

互斥锁是实现传统重入互斥体的内核对象。互斥锁允许多个线程通过确保对资源的互斥访问来安全地共享相关的硬件或软件资源。

我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总

2 概念

可以定义任何数量的互斥锁。 每个互斥量都由其内存地址引用。

互斥锁具有以下关键属性:

  • 锁定计数,指示互斥锁已被锁定的线程锁定的次数。 计数为零表示互斥锁已解锁。
  • 一个拥有线程,用于标识已锁定互斥锁的线程。

互斥量在使用之前必须初始化。这将其锁定计数设置为零。

需要使用共享资源的线程必须首先通过锁定关联的互斥锁来获得专用权限才能访问它。 如果该互斥体已被另一个线程锁定,则发出请求的线程可以选择等待该互斥体被解锁。

在锁定互斥锁后,线程可以安全地使用相关资源,只要需要; 但是,尽可能缩短锁定时间以避免对要使用该资源的其他线程产生负面影响,这是公认的较好的做法。 当线程不再需要该资源时,它必须解锁该互斥体以允许其他线程使用该资源。

任何数量的线程可能会同时等待锁定的互斥锁。当互斥锁变为解锁时,它将被等待时间最长的最高优先级线程锁定。

注意:互斥对象不适用于ISR。

2.1 可重入锁定

一个线程允许锁定已经被它锁定的互斥锁。这使得线程可以在互斥量可能已经或可能未被锁定的期间上访问相关资源。

一个线程重复锁定的互斥锁需要解锁相同次数,才能完全解锁,以便可以由另一个线程声明。

2.2 优先继承

已锁定互斥锁的线程有资格获得优先级继承。这意味着如果更高优先级的线程开始等待互斥量,内核将暂时提升线程的优先级。 这允许拥有线程完成其工作并通过以与等待线程相同的优先级执行来更快速地释放互斥体。 一旦互斥锁被解锁,解锁线程会将其优先级重置为锁定该互斥锁之前的级别。

CONFIG_PRIORITY_CEILING 配置选项限制了由于优先级继承而导致内核可以提高线程优先级的程度。 默认值0允许无限升高。

当两个或更多线程等待由较低优先级线程保持的互斥量时,内核会在每次线程开始等待(或放弃等待)时调整拥有线程的优先级。 当最终解锁互斥锁时,解锁线程的优先级正确地恢复到原来的非高优先级。

当一个线程同时持有两个或多个互斥锁时,内核不完全支持优先级继承。 当所有互斥锁被释放时,这种情况可能导致线程的优先级不会恢复到原来的非高优先级。 建议在不同优先级的线程之间共享多个互斥锁时,线程只锁定一个互斥锁。

3 操作

3.1 定义互斥锁

互斥锁是使用 struct k_mutex 类型的变量定义的。它必须通过调用 k_mutex_init() 来初始化。

以下代码定义并初始化互斥锁。

struct k_mutex my_mutex;

k_mutex_init(&my_mutex);

或者,可以通过调用 K_MUTEX_DEFINE 在编译时定义和初始化互斥锁。

以下代码与上面的代码段具有相同的效果。

K_MUTEX_DEFINE(my_mutex);

3.2 锁定互斥锁

通过调用 k_mutex_lock() 来锁定互斥锁。

以下代码构建在上面的示例上,并且如果互斥体已被另一个线程锁定,它将无限期地等待互斥体变为可用。

k_mutex_lock(&my_mutex, K_FOREVER);

以下代码最多等待100毫秒以使互斥锁可用,并在互斥锁不可用时发出警告。

if (k_mutex_lock(&my_mutex, K_MSEC(100)) == 0) {
    /* mutex successfully locked */
} else {
    printf("Cannot lock XYZ display\n");
}

3.3 解锁互斥锁

通过调用 k_mutex_unlock() 解锁互斥锁。

以下代码基于上面的示例构建,并解锁先前被该线程锁定的互斥锁。

k_mutex_unlock(&my_mutex);

4 建议用法

使用互斥锁来提供资源(如物理设备)的独占访问权限。

5 配置选项

CONFIG_PRIORITY_CEILING

6 APIs

下列互斥锁API,都在 kernel.h 中提供了:

K_MUTEX_DEFINE
k_mutex_init()
k_mutex_lock()
k_mutex_unlock()

<think>好的,我需要回答用户关于互斥锁是否具备优先级继承机制的问题。首先,我应该回忆互斥锁的基本概念和优先级继承机制的作用。 互斥锁主要用于保护共享资源,防止多个线程同时访问导致数据不一致。而优先级继承机制是为了解决优先级反转问题。优先级反转是指高优先级任务被低优先级任务阻塞,因为低优先级任务持有某个共享资源,而中间优先级的任务抢占了CPU,导致高优先级任务无法执行。 接下来,我需要明确互斥锁是否普遍带有优先级继承机制。根据之前的知识,并非所有的互斥锁实现都默认支持优先级继承。例如,在实时操作系统(RTOS)中,如FreeRTOS或VxWorks,通常会提供带有优先级继承的互斥锁,以提高系统的实时性。而普通的操作系统,比如Linux的默认互斥锁可能不支持,或者需要显式配置。 然后,应该考虑不同操作系统或RTOS的具体实现差异。例如,FreeRTOS中的互斥锁确实实现了优先级继承,而POSIX线程中的互斥锁可能需要设置属性才能启用。用户可能想知道这些细节,所以需要分点说明不同环境下的情况。 另外,要解释优先级继承机制如何工作。当高优先级任务请求被低优先级任务持有的锁时,系统会暂时提升低优先级任务的优先级,使其尽快释放锁,从而减少高优先级任务的等待时间。这需要互斥锁内部有机制来跟踪持有者和请求者,并调整优先级。 用户可能还会混淆互斥锁和其他同步机制,如信号量,是否也有优先级继承。需要指出通常优先级继承是针对互斥锁设计的,因为信号量可能不持有者信息。 最后,应该总结互斥锁是否有优先级继承取决于具体实现和配置,建议在需要实时性的系统中选择支持该机制的互斥锁,并正确使用它们以避免优先级反转问题。同时,提醒用户查阅所用系统的文档以确认特性支持情况。</think>### **互斥锁的优先级继承机制** #### **1. 优先级继承的核心作用** 优先级继承(Priority Inheritance)是解决 **优先级反转(Priority Inversion)** 的关键机制。其核心逻辑为: **当高优先级任务(A)因等待低优先级任务(B)持有的锁而阻塞时,系统会临时将 B 的优先级提升至与 A 相同**,迫使 B 尽快释放锁,减少 A 的阻塞时间。 --- #### **2. 互斥锁是否支持优先级继承?** **答案取决于具体实现**: - ✅ **实时操作系统(RTOS)**: 如 FreeRTOS、VxWorks、Zephyr 等,其互斥锁 **默认支持优先级继承**。 例如 FreeRTOS 的互斥锁 API: ```c xSemaphoreCreateMutex() // 创建支持优先级继承的互斥锁 ``` - ⚠️ **通用操作系统(如 Linux)**: 普通互斥锁(`pthread_mutex_t`)默认 **不启用优先级继承**,需通过属性显式设置: ```c pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); // 启用优先级继承 ``` - ❌ **简易互斥锁实现**: 部分轻量级库或裸机代码的互斥锁可能 **完全不支持优先级继承**。 --- #### **3. 优先级继承的工作流程** 以 FreeRTOS 为例: 1. **高优先级任务 A** 请求已被 **低优先级任务 B** 持有的互斥锁,进入阻塞状态。 2. 系统将 **B 的优先级临时提升至与 A 相同**。 3. B 因优先级提升抢占 CPU,快速执行并释放锁。 4. A 成功获取锁后,系统 **恢复 B 的原始优先级**。 --- #### **4. 优先级继承的局限性** - **链式阻塞**:若任务 B 依赖另一个低优先级任务 C 的资源,仍需递归提升优先级(部分系统支持 **嵌套优先级继承**)。 - **额外开销**:优先级动态调整增加上下文切换和调度复杂度。 - **非实时系统兼容性**:在非实时环境中(如桌面系统),优先级继承可能未被严格保障。 --- #### **5. 如何验证互斥锁是否支持优先级继承?** - **查阅文档**:RTOS 通常明确标注互斥锁是否支持优先级继承。 - **代码测试**: ```c // FreeRTOS 示例:创建互斥锁后,阻塞高优先级任务观察行为 SemaphoreHandle_t mutex = xSemaphoreCreateMutex(); xSemaphoreTake(mutex, portMAX_DELAY); // 低优先级任务获取锁 // 高优先级任务请求同一锁时,低优先级任务优先级应被临时提升 ``` --- #### **6. 优先级继承 vs 优先级天花板(Priority Ceiling)** | **机制** | **优先级继承** | **优先级天花板** | |------------------|-----------------------------------|-------------------------------------| | **原理** | 动态提升持有者优先级 | 预先为锁分配固定最高优先级 | | **实时性** | 灵活,但可能多次调整 | 确定性高,减少上下文切换 | | **适用场景** | 复杂依赖关系 | 资源访问路径明确的硬实时系统 | --- ### **总结** - **支持优先级继承的互斥锁** 是实时系统的核心特性,能有效缓解优先级反转问题。 - 在 Linux 等通用系统中,需显式配置才能启用该机制。 - 设计实时任务时,应优先选择支持优先级继承的互斥锁,并评估其性能影响。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值