当前位置: 首页 > news >正文

信号量笔记

 1、信号量简介

信号量是一种实现任务间通信机制,可以实现任务之间同步临界资源的互斥访问,常用于协助一组相互竞争的任务来访问临界资源。在多任务系统中,各任务之间需要同步或互斥实现临界资源的访问,信号量功能可以为用户提供这方面的支持。

抽象的来讲,信号量是一个非负整数,所有获取它的任务都会将该整数减一,当该整数值为零时,所有试图获取它的任务都将处于阻塞状态。通常一个信号量的计数值用于对应有效的资源数,表示剩下的可被占用的互斥资源数。

信号量的计数值都有限制:限定最大值。

如果最大值被限定为1,那么它就是二值信号量

如果最大值不是1,它就是计数型信号量

---------------------------------------------------------------------------------------------------------------------------------队列与信号量的对比

---------------------------------------------------------------------------------------------------------------------------------

2、二值信号量

简介

二值信号量的本质是一个队列长度为1的队列,该队列只有空和满两种情况,这就是所谓的二值。

二值信号量通常用于互斥访问或任务同步,与互斥信号量比较类似,但是二值信号量有可能会导致优先级翻转的问题,所以二值信号量更适合用于同步

什么是同步啊?举个例子吧。

用作同步时,信号量在创建后应被置为空,任务1获取信号量而进入阻塞状态,任务2在某种条件发生后,任务2运行并在最后释放信号量,于是任务1获得信号量得以进入就绪态,如果任务1的优先级是最高的,那么就会立即切换任务,任务1执行完成后并不需要归还信号量,从而达到了两个任务间的同步。同样的,在中断服务函数中释放信号量,任务1也会得到信号量,从而达到任务与中断间的同步。

---------------------------------------------------------------------------------------------------------------------------------

这里有一个知识点,优先级翻转

顾名思义,优先级翻转的意思就是高优先级的任务反而慢执行,而低优先级的任务反而优先执行。

优先级翻转在抢占式内核中是非常常见的,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破坏任务的预期顺序,可能会导致未知的严重后果。

这么纯说还是有一些抽象,那我要拿出正点原子的例子并解释一通了。

前提条件:任务L的优先级最低,M的优先级中,H的优先级最高;任务L和H的开头和结尾需要获取信号量然后释放信号量,任务M不需要。

L先执行,然后H想要执行,但是信号量的计数值此时为0,H没有办法执行而进入阻塞状态,所以L继续执行,然后M执行,因为M不需要信号量,所以M执行,等M和L都执行完,H才能执行,这个时候就会出现M优先级比H低,但是M先于H执行。

高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转)

---------------------------------------------------------------------------------------------------------------------------------

上一张信号量的图吧。

相关API函数

使用二值信号量的流程与队列类似,使用二值信号量的流程为:创建二值信号量、释放二值信号量、获取二值信号量。

后边的计数信号量和互斥信号量的释放和获取与这里使用的函数一致。

动态方式创建二值信号量

 #define   xSemaphoreCreateBinary( )   						xQueueGenericCreate( 1 ,   semSEMAPHORE_QUEUE_ITEM_LENGTH  ,   queueQUEUE_TYPE_BINARY_SEMAPHORE )
#define  semSEMAPHORE_QUEUE_ITEM_LENGTH      ( ( uint8_t ) 0U )

使用该函数创建的二值信号量是空的。

返回值

释放二值信号量函数

获取二值信号量函数

信号量删除函数

vSemaphoreDelete()用于删除一个信号量,包括二值信号量、计数信号量和互斥信号量。如果有任务阻塞在该信号量上,那么不要删除该信号量。

函数原型:

void vSemaphoreDelete(SemaphoreHandle_t xSemaphore);

传入参数:

信号量句柄。

3、计数型信号量

简介

计数型信号量相当于队列长度大于1的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定。

计数型信号量使用场合

事件计数:当每次事件发生后,在事件处理函数中释放计数型信号量(计数值+1),其他任务会获取计数型信号量(计数值-1),这种场合一般在创建时将初始计数值设置为0。

资源管理:信号量表示有效的资源数目。任务必须先获取信号量(信号量计数值-1)才能获取资源控制权。当计数值减为零时表示没有资源。当任务使用完资源后,必须释放信号量(信号量计数值+1)。信号量创建时计数值应等于最大资源数目。

相关API函数

动态方式创建计数型信号量

获取信号量的计数值函数

4、互斥信号量

简介

互斥信号量其实就是一个拥有优先级继承的二值信号量,互斥信号量适合用于那些需要互斥访问的应用中。

用作互斥时,信号量创建后可用信号量个数应该是满的,任务在需要使用临界资源时(临界资源是指任何时刻只能被一个任务访问的资源),先获取互斥信号量,使其变空,这样其他任务需要使用临界资源时就会因为无法获取信号量而进入阻塞,从而保证了临界资源的安全。

在操作系统中,我们使用信号量的很多时候是为了给临界资源建立一个标志,信号量表示了该临界资源被占用情况。这样,当一个任务在访问临界资源的时候,就会先对这个资源信息进行查询,从而在了解资源被占用的情况之后,再做处理,从而使得临界资源得到有效的保护。

---------------------------------------------------------------------------------------------------------------------------------

优先级继承:当一个互斥信号量正在被一个低优先级的任务持有时,如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

优先级继承并不能完全消除优先级翻转的问题,它只能尽可能的降低优先级翻转带来的影响。

H把L的优先级提升到与自己相同,那么M就不能抢占L。

---------------------------------------------------------------------------------------------------------------------------------

互斥信号量不能用于中断服务函数中,原因如下:

(1)互斥信号量有任务优先级继承的机制,但是中断不是任务,没有任务优先级,所以互斥信号量只能用于任务中,不能用于中断服务函数。

(2)中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

相关API函数

互斥信号量创建API函数(动态)

注意:创建互斥信号量时,会主动释放一次信号量。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • pytorch FSDP分布式训练minist案例
  • java springboot 集成activeMQ(保姆级别教程)
  • C++学习笔记——交换值
  • Unity3D UGUI性能消耗和管理详解
  • Redis集群技术
  • CSS3页面布局-三栏-中栏流动布局
  • 基于无人机边沿相关 ------- IBUS、SBUS协议和PPM信号
  • 目标检测:Cascade R-CNN: Delving into High Quality Object Detection - 2017【方法解读】
  • 张宇36讲+1000题重点强化!保100冲120速刷攻略
  • <WPF> xaml代码如何使用c#编写
  • 《一种个性化逻辑定制与类置换方案》
  • Android原生JobSchedulerContext内存泄漏导致设备重启的现象
  • java中位运算在算法中的应用
  • Ubuntu2004编译VLC-QT(记录)(根据官方步骤来)
  • 【ES6新特性】介绍ES6新特性的内容,如var,Let,Const声明变量的区别,解构赋值的概念,字符串的扩展,数组的扩展,以及对象的扩展。
  • JS 中的深拷贝与浅拷贝
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Bytom交易说明(账户管理模式)
  • centos安装java运行环境jdk+tomcat
  • CentOS从零开始部署Nodejs项目
  • CSS 三角实现
  • Git初体验
  • Javascripit类型转换比较那点事儿,双等号(==)
  • Less 日常用法
  • OSS Web直传 (文件图片)
  • Service Worker
  • V4L2视频输入框架概述
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 解决iview多表头动态更改列元素发生的错误
  • 入口文件开始,分析Vue源码实现
  • 思维导图—你不知道的JavaScript中卷
  • 算法之不定期更新(一)(2018-04-12)
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​如何在iOS手机上查看应用日志
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (2)Java 简介
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (6)设计一个TimeMap
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Java数据结构)ArrayList
  • (备忘)Java Map 遍历
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • .htaccess 强制https 单独排除某个目录
  • .Net 8.0 新的变化
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • ::
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • [ Socket学习 ] 第一章:网络基础知识
  • [000-002-01].数据库调优相关学习