基本概念

  • 抽象的来讲,信号量是一个非负整数,所有获取它的任务都会将该整数减一(获取它当然是为了使用资源),当该整数值为零时,所有试图获取它的任务都将处于阻塞状态

二值信号量

  • 二值信号量既可以用于临界资源访问也可以用于同步功能

  • 互斥量有优先级继承机制,二值信号量则没有这个机制

  • 二值信号量更偏向应用于同步功能(任务与任务间的同步或任务和中断间同步)

  • 而互斥量更偏向应用于临界资源的访问

  • 将二值信号量看作只有一个消息的队列因此这个队列只能为空或满

计数信号量

  • 计数信号量肯定是用于计数的
  • 信号量的计数值则表示还有多少个事件没被处理
  • 计数型信号量允许多个任务对其进行操作,但限制了任务的数量

互斥信号量

  • 互斥信号量其实是特殊的二值信号量,由于其特有的优先级继承机制从而使它更适用于简单互锁,也就是保护临界资源
  • 信号量创建后可用信号量个数应该是满的

递归信号量

  • 任务成功获取几次递归互斥量,就要返还几次,在此之前递归互斥量都处于无效状态,只有持有递归信号量的任务才能获取与释放
  • 对于已经获取递归互斥量的任务可以重复获取该递归互斥量,该任务拥有递归信号量的所有权

信号量控制块

  1. 使用信号量需要包含头文件
#include <semphr.h>
  1. 信号量控制块结构体与消息队列结构体是一模一样的,只不过结构体中某些成员变量代表的含义不一样而已
typedef struct QueueDefinition
{int8_t *pcHead;                    int8_t *pcTail;                 int8_t *pcWriteTo;              union                           {int8_t *pcReadFrom;            UBaseType_t uxRecursiveCallCount;} u;List_t xTasksWaitingToSend;        List_t xTasksWaitingToReceive;  volatile UBaseType_t uxMessagesWaiting;/* 表示有效信号量个数
1. 如果信号量是二值信号量、互斥信号量,这个值是 1 则表示有可用信号量,如果是 0 则表示没有可用信号量。2. 如果是计数信号量,这个值表示可用的信号量个数,在创建计数信号量的时候会被初始化一个可用信号量个数 uxInitialCount,最大不允许超过创建信号量的初始值 uxMaxCount。
*/UBaseType_t uxLength;         /*
最大的信号量可用个数,
1. 如果信号量是二值信号量、互斥信号量,uxLength 最大为 1,因为信号量要么是有效的,要么是无效的。
2. 如果是计数信号量,这个值表示最大的信号量个数,在创建计数信号量的时候将由用户指定这个值 uxMaxCount。*/UBaseType_t uxItemSize;           /*果控制块结构体被用于信号量的时候,则无需存储空间,为 0 即可 */volatile int8_t cRxLock;      volatile int8_t cTxLock;        #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated;  #endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;

信号量句柄

typedef QueueHandle_t SemaphoreHandle_t;

创建二值信号量 xSemaphoreCreateBinary()

#define semSEMAPHORE_QUEUE_ITEM_LENGTH       ( ( uint8_t ) 0U )#define queueQUEUE_TYPE_BASE              ( ( uint8_t ) 0U )
#define queueQUEUE_TYPE_SET                 ( ( uint8_t ) 0U )
#define queueQUEUE_TYPE_MUTEX               ( ( uint8_t ) 1U )
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE  ( ( uint8_t ) 2U )
#define queueQUEUE_TYPE_BINARY_SEMAPHORE    ( ( uint8_t ) 3U )
#define queueQUEUE_TYPE_RECURSIVE_MUTEX     ( ( uint8_t ) 4U )#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
  • 没有消息存储空间的队列,信号量用什么表示?其实二值信号量的释放和获取都是通过操作队列结控制块构体成员uxMessageWaiting 来实现的,它表示信号量中当前可用的信号量个数

创建计数信号量 xSemaphoreCreateCounting()

 #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
/*
uxMaxCount          计数信号量的最大值,当达到这个值的时候,信号量不能再被释放。
uxInitialCount  创建计数信号量的初始值。
返回值                 如果创建成功则返回一个计数信号量句柄,用于访问创建的计数信号量。如果创建不成功则返回 NULL。
*/

信号量删除函数 vSemaphoreDelete()

void vSemaphoreDelete( SemaphoreHandle_t xSemaphore )#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )

信号量释放函数–普通版


BaseType_t xSemaphoreGive(SemaphoreHandle_t  xSemaphore )   #define xSemaphoreGive( xSemaphore )        xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
/*
如果信号量满,则返回错误代码(err_QUEUE_FULL)
*/

信号量释放函数–中断版

它不能释放互斥量,这是因为互斥量不可以在中断中使用,互斥量的优先级继承机制只能在任务中起作用,而在中断中毫无意义。


#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )  xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )/*
如果被唤醒的任务的优先级大于当前任务的优先级,那么形参 pxHigherPriorityTaskWoken 就会被设置为 pdTRUE,然后在中断退出前执行一次上下文切换,从 FreeRTOS V7.3.0 版本开始 xHigherPriorityTaskWoken 是一个可选的参数,可以设置为 NULL
*/

信号量获取函数–普通版

#define xSemaphoreTake( xSemaphore, xBlockTime )     xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
/*xSemaphore        信号量句柄。
xBlockTime      等待信号量可用的最大超时时间,单位为 tick(即系统节拍周期)。如果宏 INCLUDE_vTaskSuspend 定义为 1 且形参xTicksToWait 设置为 portMAX_DELAY ,则任务将一直阻塞在该信号量上(即没有超时时间)。
返回值             获 取 成 功 则 返 回 pdTRUE , 获取失败 返 回 errQUEUE_EMPTY。
*/

信号量获取函数–中断版

获取信号量,是一个不带阻塞机制获取信号量的函数,获取对象必须由是已经创建的信号量,信号量类型可以是二值信号量和计数信号量,它与 xSemaphoreTake()函数不同,它不能用于获取互斥量,因为互斥量不可以在中断中使用,并且互斥量特有的优先级继承机制只能在任务中起作用,而在中断中毫无意义。

#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )   xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )

6.FreeRTOS学习笔记-信号量相关推荐

  1. freeRtos学习笔记 (7)信号量

    freeRtos学习笔记 freeRtos信号量 信号量种类 信号量分为四种:二值信号量,互斥信号量,计数信号量和递归互斥信号量,其中计数信号量用于管理系统多个共享资源,用计数值表示可用资源数目;二值 ...

  2. FreeRTOS学习笔记——互斥型信号量

    来自:http://blog.csdn.net/xukai871105/article/details/43456985 0.前言 在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段.下面结合一 ...

  3. FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析

    FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析 怎么查找就绪任务中优先级最高的? tasks.c中声明了一个全局变量 uxTopReadyPriority,任务从其他状态进入就绪 ...

  4. freeRtos学习笔记 (8) 任务通知

    freeRtos学习笔记 freeRtos任务通知 任务通知的优缺点 freeRtos任务控制块中包含两个32位的变量,用于任务通知,在一些情况下,任务通知可以替代信号量和事件组,并且比信号量和事件组 ...

  5. freeRtos学习笔记 (5)事件组

    freeRtos学习笔记 freeRtos事件组 为什么要用事件组? 多任务环境下, 任务.中断之间往往需要同步操作,一个事件发生会告知等待中的任 务,即形成一个任务与任务.中断与任务间的同步.事件可 ...

  6. FreeRTOS学习笔记

    FreeRTOS学习笔记 (这是我自己学习FreeRTOS整理的笔记,仅供参考) 第一部分:实现FreeRTOS内核 变量名: 定义变量时往往会把变量的类型当作前缀加在变量上 变量类型 前缀 char ...

  7. 1、野火freertos学习笔记

    野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...

  8. freeRtos学习笔记 (9) 移植和CPU利用率统计

    freeRtos学习笔记 (9) 移植和CPU利用率统计 使用官方固件移植 首先准备一个能跑的裸机工程 注意,freertos需要使用systick定时器,而stm32HAL库默认使用systick作 ...

  9. freeRtos学习笔记 (6)软件定时器

    freeRtos学习笔记 freeRtos软件定时器 软件定时器需要注意事项 软件定时器的精度基于时钟节拍,例如系统时钟节拍为10ms, 软件定时器定时时间必须是10ms的整数倍,因此软件定时器一般用 ...

最新文章

  1. 9,线程池 threadPool 与 线程池执行器 threadPoolExecutor
  2. docker centos7 安装ssh
  3. 电脑分辨率是什么_吵翻天的2K、3K、4K屏到底是什么鬼?
  4. [Jetty]基于Java Servlet的支持WebSocket的服务器
  5. Linux驱动中相关函数查询
  6. CAD迷你看图 for Mac(MiniCAD)
  7. python 移动文件或文件夹操作
  8. 可用等式为:html+java=jsp表示jsp[8]._在 JSP 中 , 对 jsp:setProperty 标记描述正确的是 ()_学小易找答案...
  9. 酒店管理系统(功能结构图、E-R图、用例图)
  10. 【Spring Boot】——集成JSON工具
  11. signature=ac75cb7977a45c0f7d8a73dca59a4c27,合肥2016年8月24日至2016年9月5日交通违章查询...
  12. uniapp微信授权+获取手机号+解密手机号(带图详解)
  13. 关于小米路由器的局域网内相互ping设备IP的解决方法
  14. 历史回顾|创建PG全球生态!PostgresConf.CN2019大会召开
  15. 鸿蒙系统与麒麟os,华为鸿蒙系统改名为麒麟OS
  16. 目前市面上最受欢迎共享产品有哪些
  17. 关于FLEX输出时:IE提示Alternate HTML content should be placed here. This content requir
  18. 互联网商业模式有哪些?
  19. Python网络爬虫实战10:爬取中关村在线首页“今日焦点”的头条新闻列表
  20. CPU 平均负载为多少更合理?

热门文章

  1. wpf tabcontrol嵌套自动跳转上层_Python Selenium包应对嵌套网页的方法和简单 js 脚本运行的实现...
  2. 1gb 云服务器 和2gb的区别_(12)虚拟主机/VPS/云主机/服务器有什么区别?
  3. mysql 不完全插入_MySql insert插入操作不完全指北_MySQL
  4. cad画圆如何确定圆心_原来在CAD中画个圆也有这么多学问!你知道这些画圆的技巧吗?...
  5. Java 并发编程之 CopyOnWriteArrayList
  6. Java 算法 特殊的数字四十
  7. Java 算法 数列
  8. python使用zip迭代列表
  9. Java反射运行时_java反射获得运行时属性的值
  10. java se开发_JAVA_SE基础——3.Java程序的开发流程