您的位置:首页 > 文旅 > 旅游 > 信号量笔记

信号量笔记

2024/10/6 12:32:32 来源:https://blog.csdn.net/2301_78455117/article/details/141533885  浏览:    关键词:信号量笔记

 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函数(动态)

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com