目录
说明:
一、信号量
1.1、信号量简介
1.2、信号量特点
二、二值信号量
2.1、二值信号量简介
2.2、获取与释放二值信号量函数
2.3、二值信号量使用过程与相关API函数
2.4、创建二值信号量函数了解
2.5、释放二值信号量了解
2.6、获取二值信号量了解
三、计数型信号量
3.1、计数型信号量简介
3.2、计数型信号量适用场合
3.3、创建计数型信号量函数
3.4、获取信号量当前数值大小函数
3.5、计数型信号量释放与获取
四、优先级翻转
4.1、什么是优先级翻转
4.2、优先级翻转出现原因
4.3、解决优先级翻转
五、互斥信号量
5.1、什么是互斥信号量
5.2、什么是优先级继承
说明:
关于内容:
1)以下内容多为概念了解与步骤分析
2)暂无个人示例代码,使用的是FreeRTOS的官方示例代码
3)若想移植代码测试的,请移步其它地方寻找,下文内容暂无个人示例代码供测试
关于其它:
1)操作系统:win 10
2)平台:keil 5 mdk
3)语言:c语言
4)板子:STM32系列移植FreeRTOS
一、信号量
1.1、信号量简介
1)信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。
2)信号量资源数表示共享资源的数量(称为计数值,计数值大于0表示有信号量资源)
3)释放信号量表示让出共享资源,计数值+1(因为共享资源空位多了)
4)获取信号量表示占用共享资源,计数值-1(因为共享资源空位少了)
5)信号量的计算值有限制:限定最大值,当限定最大值为1-->它就是二值信号量;让最大值不是1-->它就是计数型信号量
1.2、信号量特点
1)仅存放计数值,无法存放其它数据;创建信号量,只需分配信号量结构体
2)释放信号量时,不可阻塞,计数值+1,当计数值最大值时,返回失败
3)获取信号量,计数值-1,当没有资源时,可以阻塞
二、二值信号量
2.1、二值信号量简介
1)二值信号量本质是一个队列长度为1的队列,故该队列只存在空或满两种情况,这就是二值的意思
2)二值信号量通常用于互斥访问或任务同步,与互斥信号量相似,但二值信号量可能导致优先级翻转问题,故二值信号量多用于任务同步
2.2、获取与释放二值信号量函数
1)释放二值信号量函数:xSemaphoreGive(任务中),xSemaphoreGiveFromISR(中断中)
2)获取二值信号量函数:xSemaphoreTake(任务中),xSemaphoreTakeFromISR(中断中)
3)Give相当于把标志置“满”-->相当于1,Take相当于把标志置“空”-->相当于0
2.3、二值信号量使用过程与相关API函数
1)首先创建二值信号量-->释放二值信号量-->获取二值信号
2)相关API函数,如下图1:
图1
2.4、创建二值信号量函数了解
函数名称:SemaphoreHandle_t xSemaphoreCreateBinary(void)
或使用创建队列函数,代入不同参数即可,如下图2:
图2
返回值:
返回值为,NULL,表示:创建失败
返回值为,其他值,表示:创建成功返回二值信号的句柄
2.5、释放二值信号量了解
函数名称:BaseType_t xSemaphoreGive(xSemaphore)
参数:
xSemaphore,含义:要获取的信号量句柄
2.6、获取二值信号量了解
函数名称:BaseType_t xSemaphoreTake( xSemaphore,xBlockTime)
参数:
xSemaphore,含义:要获取的信号量句柄
xBlockTime,含义:阻塞时间
返回值:
pdTRUE,含义:获取信号量成功
pdFALSE,含义:超时,获取信号量失败
三、计数型信号量
3.1、计数型信号量简介
计数型信号量相当于队列长度大于1的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的。
3.2、计数型信号量适用场合
1)事件计数:当每次事件发生后,在事件处理函数释放计数型信号量(计数值+1),其他任务会获取计数型信号量(计数值-1),这种场合一般在创建时将初始值设置为0;
2)资源管理:信号量表示有效的资源数目,任务必须先获取信号量(信号量计数值-1),才能获得资源控制权,当计数值为0时表示没有可用资源,当任务使用完资源后,必须释放信号量(计数值+1)。信号量创建时计数值应大于最大资源数目。
3.3、创建计数型信号量函数
函数名称:xSemaphoreCreateCounting(uxMaxCount, uxlnitalCount)
3.4、获取信号量当前数值大小函数
函数名称:xSemaphoreGetCount(xSemaphore)
3.5、计数型信号量释放与获取
同二值信号量,不在说明。
四、优先级翻转
4.1、什么是优先级翻转
高优先级的任务反而慢执行,低优先级的任务先执行。优先级翻转在强占式内核中是很常见的,但在实时操作系统中是不允许被出现优先级翻转的,因为优先级翻转会破坏任务的预期允许顺序,可能导致未知的严重后果。
4.2、优先级翻转出现原因
1)假设存在三个任务A,B,C,任务A优先级最高(在ABC任务中,下同),任务B优先级中间,任务C优先级最低;任务A和任务C都是对二值信号量进行申请的;任务B执行其他功能(例如打印信息)
2)任务C先被创建,故C先运行(此时任务A刚刚就绪,此时任务B未就绪),任务A也申请二值信号量,但此时任务C已占用,任务A申请不到,只能被阻塞进行等待;此时任务B就绪了,因为任务B不申请二值信号量,且优先级高于任务C,所以任务B抢占了任务C;此时就会出现,任务A优先级>任务B优先级,但任务B却先运行的情况;
3)高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。从现象看,就像是中优先级的任务比高优先级任务具有更高的优先级。
4.3、解决优先级翻转
1)优先级继承(互斥信号量)
2)优先级天花板
五、互斥信号量
5.1、什么是互斥信号量
互斥信号量其实就是一个拥有优先级继承二值信号量,在同步的应用中二值信号量最合适。互斥信号量适用于那些需要互斥访问的应用中。
5.2、什么是优先级继承
当一个互斥信号量正在被一个低优先级的任务持有时,如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务将会将优先级的提升到与自己相同的优先级。
注意点:
1)互斥信号量不能用于中断服务函数中,原因:1、互斥信号量有任务优先级继承的机制,但是中断不是任务,没有任务优先级,所以互斥信号量只能用于任务中,不能用于中断服务函数中;2、中断服务函数不能因为要等待互斥信号量而设置阻塞时间进入阻塞态
2)创建互斥信号量时,会主动释放一次信号量。