STM32与FreeRTOS结合应用中的信号量详解

信号量:

        它为一个经典的同步工具,用来处理线程同步问题,尤其是共享资源的访问控制。

FreeRTOS的两个主要信号量类型:二值信号量计数信号量。其中二值信号量包含一特殊“互斥型信号量”

一、二值信号量

定义:

        仅能储存2种状态值,用于在任务之间同步或实现简单的二进制状态的互斥访问。

作用:

        1、同步:

                可以像普通的信号量一样用于任务间的同步

        2、简单的互斥访问:

                它也可以用于简单的互斥访问共享资源(类似于互斥锁)。当一个任务获取了二值信号量,其他任务在获取该信号量时会被阻塞,直到它被释放。

特点:

        1、二值信号量是数值型信号量的特殊形式:

                计数范围为0或1。

        2、它没有内置的优先级继承机制

                当低优先级任务正持有某二值信号量时,高优先级任务由于无法获取信号量的值而被阻塞,就是说高优先级任务无法先一步低优先级任务执行,在执行效果上优先级被反转。显然违背了实时操作系统的实时性。

使用:

       1、 创建:(动态)

                使用 xSemaphoreCreateBinary() 或 xSemaphoreCreateBinaryStatic() 函数创建二值信号量。

        定义信号量类型变量接受信号量句柄:

                SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary(void);//该函数无参数,初始信号量为0(不可用)。

                创建成功返回信号量句柄,创建失败返回NULL。

        显式激活:

                二值信号量初始值为0,需要手动激活:

                xSemaphoreGive(xBinarySemaphore); // 将信号量设置为 1

        2、创建:(静态)

        分配静态缓冲区:

                StaticSemaphore_t xStaticSemaphoreBuffer;

        创建静态二值信号量,将静态缓冲区作为参数传递:

        定义信号量类型变量接受信号量句柄:

                SemaphoreHandle_t xSemaphore =

                                     xSemaphoreCreateBinaryStatic( &xStaticSemaphoreBuffe );

        显式激活:

                二值信号量初始值为0,需要手动激活:

                xSemaphoreGive(xBinarySemaphore); // 将信号量设置为 1

二值信号量无优先级继承机制!!!!!

二值信号量无优先级继承机制!!!!!

二、计数型信号量(多值信号量)

        多值信号量的核心功能应该是允许多个任务共享资源,同时还能控制资源的并发访问数量。它更侧重于资源的管理和分配。任务间通信可以用信号量来同步事件,比如一个任务生成事件,另一个任务等待事件;资源管理则是用信号量来控制对共享资源的访问,比如多个任务访问多个打印机。这些例子很好懂,我可以直接用。

使用:(动态)

        创建多值信号量:

                SemaphoreHandle_t xCountingSemaphore = xSemaphoreCreateCounting(10, 0);

                其中xSemaphoreCreateCounting的原型为:

                SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount

                , UBaseType_t uxInitialCount);

        形参解释:

                uxMaxCount:信号量的最大计数值   uxInitialCount:信号量的初始计数值

        函数返回值及其特性:

        返回值:

              成功的话返回一个指向信号量的指针(句柄),该句柄用于后续对信号量的操作。

      失败的话:如果由于内存不足等原因无法创建信号量,函数返回 NULL

        特性:

              优先级继承:

                当一个高优先级任务等待一个由低优先级任务持有的资源时,FreeRTOS 会通过临时提升低优先级任务的优先级来避免优先级翻转问题。

                 优先级继承机制由系统自动完成 无需用户显性操作。

        获取信号量:

                使用BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);

        参数解释:

                xSemaphore:  信号量句柄,该值必须使用创建信号量的函数获取    

        xTicksToWait:任务等待信号量的最长时间(单位为 ticks)。如果设置为portMAX_DELAY,任务将无限等待,直到信号量变为可用状态。

        返回值:

                pdPASS:成功获取信号量。

                pdFAIL:未获取到信号量,可能是信号量不可用且等待时间已到,或参数不合法。

三、互斥型信号量(互斥锁)

        互斥锁是一种特殊的二进制信号量,用于保护临界资源,确保同一时刻只有一个线程能够访问共享资源。它只有2种状态:开锁(未被占用)与关锁(被占用)。

        互斥锁的闭锁状态(即被占用状态)只能被一个线程持有:

        一旦某个线程获取互斥锁后,互斥锁变为闭锁状态,其他线程无法获取该锁。

        工作原理:

  1.  加锁:当线程需要访问共享资源时,会尝试获取互斥锁。如果互斥锁处于开锁状态,则线程获取锁成功,互斥锁变为闭锁状态,线程可以访问资源
  2. 阻塞等待如果互斥锁已被其他线程占用(闭锁状态),则当前线程会被阻塞,进入等待队列,直到互斥锁被释放
  3. 解锁:当持有互斥锁的线程完成对共享资源的访问后,会释放互斥锁,互斥锁变为开锁状态。此时,等待队列中的线程会被唤醒,尝试获取互斥锁。

        特性:

  1. 互斥性:确保同一时刻只有一个线程能够访问共享资源,避免了多线程同时访问导致的数据不一致
  2. 优先级继承:为了避免优先级反转问题,互斥锁通常支持优先级继承机制。当一个低优先级线程持有互斥锁时,如果有高优先级线程请求该锁,低优先级线程的优先级会被临时提升,直到它释放锁。
  3. 递归访问:某些互斥锁支持递归访问,即同一个线程可以多次获取同一个互斥锁而不会导致死锁。
  4. 中断中的不可用:互斥锁不能在中断服务例程中使用,因为中断无法保持阻塞等待

使用:

        创建互斥锁:

                SemaphoreHandle_t xSemaphoreCreateMutex(void);

                创建成功返回互斥锁句柄,创建失败返回NULL

        获取互斥锁:

                BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,

                                                                                         TickType_t xTicksToWait);

                成功获取互斥锁返回pdTRUE;失败返回pdFALSE

        参数解释:

                xSemaphore:互斥锁句柄

                 xTicksToWait:获取互斥锁等待时间,该参数为:portMAX_DELAY时则会无限等待。

        释放互斥锁:

                BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);

                如果成功释放,返回返回pdTRUE;失败返回pdFALSE

        参数解释:

                xSemaphore:互斥锁的句柄

作者:推推发际线

物联沃分享整理
物联沃-IOTWORD物联网 » STM32与FreeRTOS结合应用中的信号量详解

发表回复