首页 > 其他分享 >信号量、事件组、任务通知:异同及替代应用分析(超细)

信号量、事件组、任务通知:异同及替代应用分析(超细)

时间:2023-12-16 10:31:29浏览次数:26  
标签:异同 通知 void 超细 信号量 任务 事件 include

在实时嵌入式系统中,信号量、事件组和任务通知是常用的同步与通信机制,它们在不同场景下有着各自的优势与适用性。本文将深入探讨这三种机制的异同,分析它们的特点及何时可以相互替代,并通过详细的代码演示展示它们的具体应用。

1. 信号量(Semaphore)

1.1 特点

  • 计数型: 信号量是一种计数型的同步机制,允许多个任务同时访问共享资源。
  • 阻塞与唤醒: 当信号量计数为0时,任务会被阻塞,直到信号量计数大于0时才能继续执行。
  • 资源争用: 信号量可以用于处理资源的争用问题,通过控制资源的访问权限。

1.2 代码演示

以下是使用FreeRTOS中的信号量实现任务同步的简单代码演示:

#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>

SemaphoreHandle_t xSemaphore;

void TaskA(void *pvParameters) {
    while (1) {
        // 等待获取信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY)) {
            // 访问共享资源
            // ...

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

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void TaskB(void *pvParameters) {
    while (1) {
        // 等待获取信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY)) {
            // 访问共享资源
            // ...

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

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

int main() {
    // 创建信号量
    xSemaphore = xSemaphoreCreateBinary();

    // 创建任务
    xTaskCreate(TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    xTaskCreate(TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    return 0;
}

2. 事件组(Event Group)

2.1 特点

  • 位掩码: 事件组使用位掩码的方式表示多个事件状态,每个位代表一个事件。
  • 等待与触发: 任务可以等待特定的位或多个位的状态,也可以触发(设置)特定的位。
  • 轻量级: 事件组相对轻量级,适用于对事件状态敏感的场景。

2.2 代码演示

以下是使用FreeRTOS中的事件组实现任务同步的简单代码演示:

#include <FreeRTOS.h>
#include <task.h>
#include <event_groups.h>

EventGroupHandle_t xEventGroup;

// 定义事件位
#define EVENT_BIT_A (1 << 0)
#define EVENT_BIT_B (1 << 1)

void TaskA(void *pvParameters) {
    while (1) {
        // 等待事件位A
        EventBits_t bits = xEventGroupWaitBits(xEventGroup, EVENT_BIT_A, pdTRUE, pdFALSE, portMAX_DELAY);

        // 访问共享资源
        // ...

        // 释放事件位A
        xEventGroupClearBits(xEventGroup, EVENT_BIT_A);

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void TaskB(void *pvParameters) {
    while (1) {
        // 触发事件位A
        xEventGroupSetBits(xEventGroup, EVENT_BIT_A);

        // 访问共享资源
        // ...

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

int main() {
    // 创建事件组
    xEventGroup = xEventGroupCreate();

    // 创建任务
    xTaskCreate(TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    xTaskCreate(TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    return 0;
}

3. 任务通知(Task Notification)

3.1 特点

  • 单一事件: 任务通知用于单一事件的通知,任务可以等待通知的到来。
  • 无阻塞等待: 任务通知支持无阻塞等待,任务可以轮询等待通知。
  • 低延迟: 任务通知的实现相对轻量,适用于对低延迟要求较高的场景。

3.2 代码演示

以下是使用FreeRTOS中的任务通知实现任务同步的简单代码演示:

#include <FreeRTOS.h>
#include <task.h>

TaskHandle_t xTaskA;
TaskHandle_t xTaskB;

void TaskA(void *pvParameters) {
    while (1) {
        // 等待任务通知
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        // 访问共享资源
        // ...

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void TaskB(void *pvParameters) {
    while (1) {
        // 发送任务通知给TaskA
        xTaskNotifyGive(xTaskA);

        // 访问共享资源
        // ...

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

int main() {
    // 创建任务
    xTaskCreate(TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskA);
    xTaskCreate(TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskB);

    // 启动调度器
    vTaskStartScheduler();

    return 0;
}

4. 异同及何时可以替代

4.1 异同点

  • 信号量: 适用于资源争用场景,支持计数,可以用于多任务的同步与互斥。
  • 事件组: 适用于多事件状态管理场景,轻量级,但不支持计数。
  • 任务通知: 适用于单一事件通知场景,轻量级,低延迟。

4.2 替代应用分析

  • 使用信号量替代事件组: 当需要对资源进行计数控制,或者需要实现互斥操作时,可以考虑使用信号量替代事件组。
  • 使用事件组替代信号量: 当需要对多个事件状态进行管理,并且不需要计数功能时,可以考虑使用事件组替代信号量。
  • 使用任务通知替代信号量或事件组: 当只有单一事件的通知需求,并且对低延迟有较高要求时,可以考虑使用任务通知替代信号量或事件组。

5. 总结

信号量、事件组和任务通知是实时嵌入式系统中常用的同步与通信机制,它们在不同场景下具有各自的优势。选择合适的机制取决于具体的应用需求,通过深入了解它们的特点及使用方式,开发者可以更灵活地应对不同的任务同步与通信问题。希望本文的详细代码演示和异同分析能够帮助读者更好地理解和应用这三种机制

标签:异同,通知,void,超细,信号量,任务,事件,include
From: https://blog.51cto.com/u_16192077/8850249

相关文章

  • 信号量
    队列二值信号量(通常用于互斥访问和任务同步互斥,与互斥信号量类似但二值信号量有可能会导致任务优先级翻转的问题所以二值信号量更适合与任务同步)。例1:信号量互斥操作若用于互斥,几个进程(或线程)往往只设置一个信号量sem,它们的操作流程如下图2-1:例2:信号量同步操作当信号量......
  • FreeRTOS中的任务优先级与单片机中断优先级的异同深析
    引言:在实时嵌入式系统开发中,任务的优先级和中断的优先级是关键的调度和响应机制。FreeRTOS提供了丰富的任务调度功能,而单片机的中断系统也具有类似的机制。本篇博客将深入探讨FreeRTOS中的任务优先级与单片机中断优先级的异同,通过代码演示展示它们的工作原理和使用方式。任务优先......
  • percpu 读写信号量 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/locking/percpu-rw-semaphore.html"Percpurwsemaphores"是一种新的读写信号量设计,针对读取操作进行了优化。传统的读写信号量存在一个问题,即当多个核心获取读取锁时,包含信号量的缓存行在各个核心的L1缓存之间反复传输,导致性能下降......
  • FreeRTOS--信号量
    示例源码基于FreeRTOSV9.0.0信号量1.概述消息队列用于传输多个数据,但是有时候只需要传递状态,这个状态值需要用一个数值表示,在这种情况下我们只需要维护一个数值,使用信号量效率更高、更节省内存。信号量用来表示资源的个数,它是特殊的队列实现,队列数据项为空。对于二值信号量......
  • C++20(信号量)
    #include<iostream>#include<semaphore>#include<thread>usingnamespacestd;std::counting_semaphore<3>csem(0);//semaphorerelease=condition_variablenotify//semaphoreacquire=condition_variablewaitvoidtask(){......
  • Windows电脑上的多开工具与云桌面有何异同
    在Windows电脑上,多开工具和云桌面是两种常见的应用方式,它们各自具有一些特点和优势。本文将就多开工具和云桌面在实际使用中的异同进行比较。多开工具多开工具是指能够帮助用户同时打开多个相同软件或游戏的应用程序。在Windows操作系统中,有许多第三方多开工具可以实现这一功能,......
  • 锁—信号量与管程
    1.基本概念互斥只有一个线程能访问临界区。临界资源多个线程可以共享系统中的资源,但是临界资源只允许一个线程在某一时刻访问。如某些变量、硬件资源。临界区访问临界资源的代码即临界区。2.信号量与管程管程(Monitors)和信号量(Semaphores)是操作系统中用于实现并发......
  • 【ARM中断系统】Cortex-A和Cortex-M中断系统异同
    1.Cortex-M中断系统以stm32中断系统为例,有以下几个关键点:中断向量表NVIC(内嵌向量中断控制器)中断使能中断服务函数1.1中断向量表中断向量表是一个表,这个表里面存放的是中断向量。中断服务程序的入口地址或存放中断服务程序的首地址称为中断向量,因此中断向量表示一系列中......
  • C++11 多线程并发 互斥量、条件变量和信号量
    互斥量Classesmutex(C++11)providesbasicmutualexclusionfacility(class)timed_mutex(C++11)providesmutualexclusionfacilitywhichimplementslockingwithatimeout(class)recursive_mutex(C++11)providesmutualexclusionfacili......
  • FreeRTOS深入教程(信号量源码分析)
    (文章目录)前言本篇文章将为大家讲解信号量,源码分析。在FreeRTOS中,信号量的实现基于队列。这种设计的思想是利用队列的特性来实现信号量,因为信号量可以被视为只能存储0或1个元素的特殊队列。在FreeRTOS中,二进制信号量(BinarySemaphore)通常由一个队列和一个计数器组成......