首页 > 其他分享 >FreeRTOS中信号量和互斥量背后的原理

FreeRTOS中信号量和互斥量背后的原理

时间:2023-12-20 11:00:53浏览次数:29  
标签:FreeRTOS void 任务 信号量 互斥 计数器

FreeRTOS是一个流行的嵌入式实时操作系统,提供了信号量和互斥量等同步机制来协调任务之间的访问共享资源。本文将深入探讨FreeRTOS中信号量和互斥量的背后原理,以及如何使用这些机制确保系统的稳定性和性能。

1. 信号量和互斥量的概念

1.1 信号量

信号量是一种计数器,用于控制多个任务对共享资源的访问。当资源可用时,信号量的计数器递增;当资源被占用时,计数器递减。任务可以通过等待信号量来获取资源,而释放资源则会增加信号量的计数。

1.2 互斥量

互斥量是一种二进制信号量,用于实现对共享资源的互斥访问。只有持有互斥量的任务才能访问共享资源,其他任务必须等待互斥量的释放。这确保了在任意时刻只有一个任务能够访问共享资源,防止了竞态条件和数据不一致性。

2. FreeRTOS中信号量的实现原理

FreeRTOS中信号量的实现基于其任务调度和内核机制。以下是一个简要的信号量实现原理:

2.1 信号量数据结构

在FreeRTOS中,信号量由一个结构体 Semaphore_t 表示,其中包含信号量计数器、等待该信号量的任务队列等信息。

typedef struct Semaphore_t {
    volatile UBaseType_t uxMaxCount;
    volatile UBaseType_t uxCount;
    List_t xTasksWaitingToReceive;
} Semaphore_t;

2.2 信号量的创建和使用

SemaphoreHandle_t xSemaphore;

void vSemaphoreExampleTask(void *pvParameters) {
    while (1) {
        // 请求获取信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdPASS) {
            // 访问共享资源
            // ...

            // 释放信号量
            xSemaphoreGive(xSemaphore);
        }

        // 其他任务逻辑
        // ...
    }
}

2.3 信号量的实现原理

当一个任务请求获取信号量时,如果信号量计数器大于零,表示资源可用,任务可以继续执行,并将计数器递减。如果计数器为零,则任务将被阻塞,加入等待队列,直到有其他任务释放信号量。

3. FreeRTOS中互斥量的实现原理

互斥量在FreeRTOS中的实现也基于任务调度和内核机制。以下是互斥量的简要实现原理:

3.1 互斥量数据结构

互斥量由结构体 QueueDefinition 表示,其中包含一个二进制信号量用于互斥访问共享资源。

typedef struct xQUEUE {
    List_t xTasksWaitingToSend;
    List_t xTasksWaitingToReceive;
    volatile UBaseType_t uxMessagesWaiting;
    UBaseType_t uxLength;
    void *pcHead;
    void *pcTail;
    volatile void *pxQueue;
    volatile UBaseType_t uxQueueNumber;
} QueueDefinition;

3.2 互斥量的创建和使用

SemaphoreHandle_t xMutex;

void vMutexExampleTask(void *pvParameters) {
    while (1) {
        // 请求获取互斥量
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdPASS) {
            // 访问共享资源
            // ...

            // 释放互斥量
            xSemaphoreGive(xMutex);
        }

        // 其他任务逻辑
        // ...
    }
}

3.3 互斥量的实现原理

互斥量的实现原理与信号量类似,不同之处在于互斥量的计数器只能是0或1。当一个任务请求获取互斥量时,如果计数器为0,表示资源可用,任务可以继续执行,并将计数器置为1。如果计数器为1,则任务将被阻塞,加入等待队列,直到有其他任务释放互斥量。

4. 代码演示

以下是一个简单的FreeRTOS程序,演示了信号量和互斥量的使用:

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

SemaphoreHandle_t xSemaphore;
SemaphoreHandle_t xMutex;

void vSemaphoreExampleTask(void *pvParameters) {
    while (1) {
        // 请求获取信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdPASS) {
            // 访问共享资源
            printf("Semaphore example task executing...\n");

            // 释放信号量
            xSemaphoreGive(xSemaphore);
        }

        // 其他任务逻辑
        // ...
    }
}

void vMutexExampleTask(void *pvParameters) {
    while (1) {
        // 请求获取互斥量
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdPASS) {
            // 访问共享资源
            printf("Mutex example task executing...\n");

            // 释放互斥量
            xSemaphoreGive(xMutex);
        }

        // 其他任务逻辑
        // ...
    }
}

int main() {
    // 创建信号量和互斥量
    xSemaphore = xSemaphoreCreateCounting(1, 1);
    xMutex = xSemaphoreCreateMutex();

    // 创建示例任务
    xTaskCreate(vSemaphoreExampleTask, "SemaphoreTask", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    xTaskCreate(vMutexExampleTask, "MutexTask", configMINIMAL_STACK_SIZE, NULL, 3, NULL);

    // 启动FreeRTOS调度器
    vTaskStartScheduler();

    // 正常情况下不会执行到这里
    return 0;
}

5. 总结

通过深入了解FreeRTOS中信号量和互斥量的实现原理,我们可以更好地理解这些同步机制在任务协作和共享资源管理中的作用。合理地使用信号量和互斥量可以确保系统的稳定性和性能,避免竞态条件和数据不一致性的问题。希望通过本文的介绍和代码演示,读者能够更加熟练地应用这些机制在FreeRTOS项目中。

标签:FreeRTOS,void,任务,信号量,互斥,计数器
From: https://blog.51cto.com/u_16192077/8904245

相关文章

  • 多线程+信号量同步线程
    实现场景:多线程+信号量实现线程同步执行线程在创建的时候并不能保证优先顺序,是异步的,如果想按照自己指定的顺序先后执行的话,可以使用一些互斥或者同步的方式;以下我是通过信号量来实现同步:信号量的类型是sem_t,需要的头文件是 #include<semaphore.h>,主要是方法是sem_init......
  • FreeRTOS--递归锁
    示例源码基于FreeRTOSV9.0.0递归锁1.概述递归锁是特殊的互斥量,允许同一任务多次获取和释放锁,而不会造成死锁;获取和释放的次数必须相同;递归锁的实现依赖于内部的uxRecursiveCallCount变量,它标记递归的次数,每次上锁加1,每次解锁减1,减为0才真正释放锁;递归锁也不能在中断内使用......
  • FreeRTOS--互斥量
    示例源码基于FreeRTOSV9.0.0互斥量1.概述互斥量用于临界资源的保护,通过互斥量,多个任务对相同资源进行的访问操作是互斥的;互斥量的核心在于谁上锁,就由谁解锁,这只是约定,FreeRTOS并没有在代码上实现这一点;互斥量是一种特殊的信号量,也是一种特殊的队列;使用互斥量,需要开启宏con......
  • 信号量
    信号量信号量是什么信号量是一种用于控制对共享资源的访问的同步机制,他可以限制同时访问共享资源的线程数量,从而避免资源的竞争和冲突。使用场景:用于多线程的并发控制,类似于限流。信号量和限流的异同信号量和限流的使用场景侧重点不同:信号量通常用于控制对共享资源的访问;......
  • 嵌入式操作系统的抉择:FreeRTOS、Linux、LiteOS的异同比较
    引言:在嵌入式系统开发中,选择合适的操作系统是至关重要的决策。FreeRTOS、Linux和LiteOS都是嵌入式领域常见的操作系统,各自具有特定的优势和应用场景。本篇博客将深入比较FreeRTOS、Linux和LiteOS之间的异同点,为嵌入式开发者提供更清晰的选择指南。1.FreeRTOS:轻量级实时操作系统Fr......
  • 信号量、事件组、任务通知:异同及替代应用分析(超细)
    在实时嵌入式系统中,信号量、事件组和任务通知是常用的同步与通信机制,它们在不同场景下有着各自的优势与适用性。本文将深入探讨这三种机制的异同,分析它们的特点及何时可以相互替代,并通过详细的代码演示展示它们的具体应用。1.信号量(Semaphore)1.1特点计数型:信号量是一种计数型的......
  • 协程与互斥锁: Kotlin Mutex的终极指南
    引言今天我们将深入研究Kotlin中的Mutex(互斥锁)原理以及在实际开发中的使用技巧。Mutex是多线程编程中的关键工具,它可以有效地解决多线程访问共享资源时可能发生的竞态条件问题。Mutex的基本原理Mutex是互斥锁的缩写,它是一种同步工具,用于保护共享资源,确保在任何时刻只有一个线程可以......
  • 信号量
    队列二值信号量(通常用于互斥访问和任务同步互斥,与互斥信号量类似但二值信号量有可能会导致任务优先级翻转的问题所以二值信号量更适合与任务同步)。例1:信号量互斥操作若用于互斥,几个进程(或线程)往往只设置一个信号量sem,它们的操作流程如下图2-1:例2:信号量同步操作当信号量......
  • FreeRTOS中的任务优先级与单片机中断优先级的异同深析
    引言:在实时嵌入式系统开发中,任务的优先级和中断的优先级是关键的调度和响应机制。FreeRTOS提供了丰富的任务调度功能,而单片机的中断系统也具有类似的机制。本篇博客将深入探讨FreeRTOS中的任务优先级与单片机中断优先级的异同,通过代码演示展示它们的工作原理和使用方式。任务优先......
  • FreeRTOS中的事件组:实现任务同步与通信的强大工具
    引言:在实时嵌入式系统中,任务同步和通信是至关重要的,而FreeRTOS提供的事件组(EventGroups)机制为实现这一目标提供了一种高效且灵活的解决方案。本篇博客将深入研究FreeRTOS中的事件组,详细介绍其原理、使用方法,以及在实际应用中的一些最佳实践。事件组原理:事件组是FreeRTOS中的一种......