前言
前面学习了RT-Thread的信号量,但信号量在一些场合使用会存在优先级翻转问题,接下来我们学习互斥量,在 RT-Thread 操作系统中,互斥量可以解决优先级翻转问题,实现的是优先级继承算法。互斥量和信号量不同的是:拥有互斥量的线程拥有互斥量的所有权,互斥量支持递归访问且能防止线程优先级翻转;并且互斥量只能由持有线程释放,而信号量则可以由任何线程释放。这里主要讲RT-Thread互斥量的工作机制、相关函数,在后面使用潘多拉开发板进行实验(STM32L475VET6)。
一、互斥量工作机制
1、在 RT-Thread 操作系统中,互斥量可以解决优先级翻转问题,实现的是优先级继承算法。优先级继承是通过在线程 A 尝试获取共享资源而被挂起的期间内,将线程 C 的优先级提升到线程 A 的优先级别,从而解决优先级翻转引起的问题。这样能够防止 C(间接地防止 A)被 B 抢占,如下图所示。优先级继承是指,提高某个占有某种资源的低优先级线程的优先级,使之与所有等待该资源的线程中优先级最高的那个线程的优先级相等,然后执行,而当这个低优先级线程释放该资源时,优先级重新回到初始设定。因此,继承优先级的线程避免了系统资源被任何中间优先级的线程抢占。
二、互斥量的相关函数
1、创建动态互斥量函数
创建一个互斥量时,内核首先创建一个互斥量控制块,然后完成对该控制块的初始化工作。
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag);
(1)入口参数:
name:互斥量的名称。
flag:互斥量标志,它可以取如下数值:RT_IPC_FLAG_FIFO 或RT_IPC_FLAG_PRIO。为 RT_IPC_FLAG_PRIO时,表示在多个线程等待资源时,将由优先级高的线程优先获得资源。为 RT_IPC_FLAG_FIFO时,表示在多个线程等待资源时,将按照先来先得的顺序获得资源。
(2)返回值:
互斥量句柄:创建成功。
RT_NULL:创建失败。
2、删除动态互斥量函数
当不再使用动态互斥量时,通过删除动态互斥量以释放系统资源。当删除一个动态互斥量时,所有等待此互斥量的线程都将被唤醒,等待线程获得的返回值是 RT_ERROR,然后系统将该互斥量从内核对象管理器链表中删除并释放互斥量占用的内存空间。
rt_err_t rt_mutex_delete(rt_mutex_t mutex);
(1)入口参数:
mutex:要删除的动态互斥量对象的句柄。
(2)返回值:
RT_EOK:删除成功。
3、创建静态互斥量函数
这里所说的创建静态互斥量也就是《RT-Thread编程指南》里面的初始化互斥量,静态互斥量对象的内存是在系统编译时由编译器分配的,一般放于读写数据段或未初始化数据段中。
rt_err_t rt_mutex_init (rt_mutex_t mutex, const char* name, rt_uint8_t flag);
(1)入口参数:
mutex:互斥量对象的句柄,它由用户提供,