FreeRTOS线程同步1---信号量

2024-09-03 03:44

本文主要是介绍FreeRTOS线程同步1---信号量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

二值信号量

二值信号量相关API函数

一般使用方法为

1.创建二值信号量

2.在一个任务中置为二值释放信号

3.在另一个任务中获取信号

计数信号量

计数型信号量相关 API 函数

使用方法

1.创建计数信号量

2.释放计数信号量

3.获得信号量的当前值

4.释放信号量

互斥信号量

互斥信号量常用API函数

使用方法


        信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。其中,“同步”指的
是任务间的同步,即信号量可以使得一个任务等待另一个任务完成某件事情后,才继续执行;
而“有序访问”指的是对被多任务或中断访问的共享资源(如全局变量)的管理,当一个任务
在访问(读取或写入)一个共享资源时,信号量可以防止其他任务或中断在这期间访问(读取
或写入)这个共享资源。

        需要包含的头文件为"semphr.h "

二值信号量

        信号量是基于队列实现的,二值信号量也不例外,二值信号量实际上就是一个队列长度为 1 的队列,在这种情况下,队列就只有空和满两种情况,这不就是二值情况吗。

事实上RTOS正是这样做的:

在创建二值信号量的函数xSemaphoreCreateBinaryStatic( )里跳转进入可以看到它是一个宏定义,会在预处理阶段直接替换为xQueueGenericCreateStatic( )静态创建了一个大小为1的队列

#if ( configSUPPORT_STATIC_ALLOCATION == 1 )#define xSemaphoreCreateBinaryStatic( pxStaticSemaphore )    xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, ( pxStaticSemaphore ), queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif /* configSUPPORT_STATIC_ALLOCATION */

二值信号量相关API函数

函数
描述
xSemaphoreCreateBinary()
使用动态方式创建 二值信号量
xSemaphoreCreateBinaryStatic()
使用静态方式创建二值信号量
xSemaphoreTake()
获取信号量
xSemaphoreTakeFromISR().
在中断中获取信号量
xSemaphoreGive()
释放信号量
xSemaphoreGiveFromISR()
在中断中释放信号量
vSemaphoreDelete()
删除信号量

一般使用方法为

1.创建二值信号量
QueueHandle_t xSemaphore;//声明二值信号量
xSemaphore = xSemaphoreCreateBinary();//创建二值信号量
2.在一个任务中置为二值释放信号
xSemaphoreGive(xSemaphore);//释放信号
3.在另一个任务中获取信号
xSemaphoreTake(xSemaphore, portMAX_DELAY);//获得信号量

注意在等待信号量的任务中应该为

while(1){if(xSemaphoreTake(xSemaphore, portMAX_DELAY);//阻塞等待{... /*具体操作*/}
}

从而达到任务阻塞等待信号的作用

计数信号量

        计数型信号量与二值信号量类似,二值信号量相当于队列长度为 1 的队列,因此二值信号
量只能容纳一个资源,这也是为什么命名为二值信号量,而计数型信号量相当于队列长度大于
0 的队列,因此计数型信号量能够容纳多个资源,这是在计数型信号量被创建的时候确定的。
计数型信号量通常用于一下两种场合:
1. 事件计数
        每次事件发生后,在事件处理函数中释放计数型信号量(计数型信号量的
资源数加 1),其他等待事件发生的任务获取计数型信号量(计数型信号量的资源数减 1),这么
一来等待事件发生的任务就可以在成功获取到计数型信号量之后执行相应的操作。在这种场合
下,计数型信号量的资源数一般在创建时设置为 0。
2. 资源管理
        计数型信号量的资源数代表着共享资源的可用数量,例如前面举例中停车
场中的空车位。一个任务想要访问共享资源,就必须先获取这个共享资源的计数型信号量,之
后在成功获取了计数型信号量之后,才可以对这个共享资源进行访问操作,当然,在使用完共
享资源后也要释放这个共享资源的计数型信号量。在这种场合下,计数型信号量的资源数一般
在创建时设置为受其管理的共享资源的最大可用数量。

计数型信号量相关 API 函数

函数
描述
xSemaphoreCreateCounting()
使用动态方式创建计数型信号量
xSemaphoreCreateCountingStatic()
使用静态方式创建计数型信号量
xSemaphoreTake()
获取信号量
xSemaphoreTakeFromISR()
在中断中获取信号量
xSemaphoreGive()
释放信号量
xSemaphoreGiveFromISR()
在中断中释放信号量
vSemaphoreDelete()
删除信号量

使用方法

1.创建计数信号量
QueueHandle_t CountSemaphore;/声明计数信号量
CountSemaphore=xSemaphoreCreateCounting( (UBaseType_t)255, (UBaseType_t)0);
/*计数信号量最大255,初始为0*/
2.释放计数信号量
/* 释放计数型信号量 */
xSemaphoreGive(CountSemaphore);
3.获得信号量的当前值
uint32_t semaphore_val = uxSemaphoreGetCount(CountSemaphore);//获得信号量值
printf("当前计数信号量%d\r\n",semaphore_val);
4.释放信号量
xSemaphoreTake(CountSemaphore,(TickType_t )portMAX_DELAY);//阻塞最大时间portMAX_DELAY

互斥信号量

        互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中(任务与任务或
中断与任务之间的同步)二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中。
在互斥访问中互斥信号量相当于一把钥匙,当任务想要访问共享资源的时候就必须先获得这把
钥匙,当访问完共享资源以后就必须归还这把钥匙,这样其他的任务就可以拿着这把钥匙去访
问资源。

        首先要介绍以下实时性问题里的”优先级翻转“

        优先级翻转的示例中,,任务 H 为最高优先级的任务,因此任务 H 执行的操作需要有较高的实时性,但是由于优先级翻转的问题,导致了任务 H 需要等到任务 L 释放信号量才能够运行,并且,任务 L 还会被其他介于任务 H 与任务 L 任务优先级之间的任务 M 抢占,因此任务 H 还需等待任务 M 运行完毕,这显然不符合任务 H 需要的高实时性要求。

        然而互斥信号量的特性中优先级继承,优先级继承尽可能的减少了高优先级任务处于阻塞态
的时间,并且将“优先级翻转”的影响降到最低。

        优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的
影响。实时应用应该在设计之初就要避免优先级翻转的发生。互斥信号量不能用于中断服务函
数中
,原因如下:
(1) 互斥信号量有任务优先级继承的机制,但是中断不是任务,没有任务优先级,所以互斥
信号量只能用与任务中,不能用于中断服务函数。
(2) 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

互斥信号量常用API函数
函数
描述
xSemaphoreCreateMutex()
使用动态方式创建互斥信号量
xSemaphoreCreateMutexStatic()
使用静态方式创建互斥信号量
xSemaphoreTake()
获取信号量
xSemaphoreGive()
释放信号量
vSemaphoreDelete()
删除信号量

        从上面中可以看出,互斥信号量除了创建函数之外,其余的获取、释放等信号量操作函数,
都与二值信号量相同。

使用方法

        同二值信号量

这篇关于FreeRTOS线程同步1---信号量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131927

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

java线程深度解析(六)——线程池技术

http://blog.csdn.net/Daybreak1209/article/details/51382604 一种最为简单的线程创建和回收的方法: [html]  view plain copy new Thread(new Runnable(){                @Override               public voi

java线程深度解析(五)——并发模型(生产者-消费者)

http://blog.csdn.net/Daybreak1209/article/details/51378055 三、生产者-消费者模式     在经典的多线程模式中,生产者-消费者为多线程间协作提供了良好的解决方案。基本原理是两类线程,即若干个生产者和若干个消费者,生产者负责提交用户请求任务(到内存缓冲区),消费者线程负责处理任务(从内存缓冲区中取任务进行处理),两类线程之

java线程深度解析(四)——并发模型(Master-Worker)

http://blog.csdn.net/daybreak1209/article/details/51372929 二、Master-worker ——分而治之      Master-worker常用的并行模式之一,核心思想是由两个进程协作工作,master负责接收和分配任务,worker负责处理任务,并把处理结果返回给Master进程,由Master进行汇总,返回给客

java线程深度解析(二)——线程互斥技术与线程间通信

http://blog.csdn.net/daybreak1209/article/details/51307679      在java多线程——线程同步问题中,对于多线程下程序启动时出现的线程安全问题的背景和初步解决方案已经有了详细的介绍。本文将再度深入解析对线程代码块和方法的同步控制和多线程间通信的实例。 一、再现多线程下安全问题 先看开启两条线程,分别按序打印字符串的

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu