FreeRTOS信号量
信号量是基于队列实现的一种解决任务间同步问题(有序访问)的机制,可以实现对共享资源的有序访问,包括二值信号量、计数型信号量和互斥信号量等。
二值信号量
实际上就是一个队列长度为 1 的队列,通常用于互斥访问或任务同步,但是会导致优先级翻转问题。
优先级翻转问题:当一个高优先级任务因获取一个被低优先级任务获取而处于没有资源状态的二值信号量时,这个高优先级的任务将被阻塞,直到低优先级的任务释放二值信号量,而在这之前,如果有一个优先级介于这个高优先级任务和低优先级任务之间的任务就绪,那么这个中等优先级的任务就会抢占低优先级任务的运行。
创建
xSemaphoreCreateBinary() 使用动态方式创建二值信号量
xSemaphoreCreateBinaryStatic() 使用静态方式创建二值信号量
获取
xSemaphoreTake() 获取信号量
如果信号量处于没有资源的状态,那么此函数可以选择将任务进行阻塞,如果成功获取了信号量,那信号量的资源数将会减 1。
xSemaphoreTakeFromISR(). 在中断中获取信号量
只能用于获取二值信号量和计数型信号量,而不能用于获取互斥信号量。
释放
xSemaphoreGive() 释放信号量
如果信号量处于资源满的状态,那么此函数可续选择将任务进行阻塞,如果成功释放了信号量,那信号量的资源数将会加 1
xSemaphoreGiveFromISR() 在中断中释放信号量
删除
vSemaphoreDelete() 删除信号量
计数型信号量
计数型信号量相当于队列长度大于0 的队列,因此计数型信号量能够容纳多个资源。包含两个场景:
事件计数: 计数型信号量的资源数一般在创建时设置为 0。每次事件发生后,在事件处理函数中释放计数型信号量(计数型信号量的资源数加 1),其他等待事件发生的任务获取计数型信号量(计数型信号量的资源数减 1),这么一来等待事件发生的任务就可以在成功获取到计数型信号量之后执行相应的操作。
资源管理: 计数型信号量的资源数一般在创建时设置为受其管理的共享资源的最大可用数量。一个任务想要访问共享资源,就必须先获取这个共享资源的计数型信号量,之后在成功获取了计数型信号量之后,才可以对这个共享资源进行访问操作,在使用完共享资源后也要释放这个共享资源的计数型信号量。
计数型信号量除了创建函数之外,其余的获取、释放等信号量操作函
数,都与二值信号量相同
创建
xSemaphoreCreateCounting() 使用动态方式创建计数型信号量
xSemaphoreCreateCountingStatic() 使用静态方式创建计数型信号量
获取
xSemaphoreTake() 获取信号量
如果信号量处于没有资源的状态,那么此函数可以选择将任务进行阻塞,如果成功获取了信号量,那信号量的资源数将会减 1。
xSemaphoreTakeFromISR(). 在中断中获取信号量
只能用于获取二值信号量和计数型信号量,而不能用于获取互斥信号量。
释放
xSemaphoreGive() 释放信号量
如果信号量处于资源满的状态,那么此函数可续选择将任务进行阻塞,如果成功释放了信号量,那信号量的资源数将会加 1
xSemaphoreGiveFromISR() 在中断中释放信号量
删除
vSemaphoreDelete() 删除信号量
互斥信号量
互斥信号量其实就是一个拥有优先级继承的二值信号量,适合用于需要互斥访问的应用中。在互斥访问中互斥信号量相当于一把钥匙,当任务想要访问共享资源的时候就必须先获得这把钥匙,当访问完共享资源以后就必须归还这把钥匙,这样其他的任务就可以拿着这把钥匙去访问资源。
优先级继承: 当一个互斥信号量正在被一个低优先级的任务持有时,如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级,这个过程就是优先级继承。优先级继承尽可能的减少了高优先级任务处于阻塞态的时间,并且将“优先级翻转”的影响降到最低。
互斥信号量不能用于中断服务函数中
- 互斥信号量有任务优先级继承的机制,但是中断不是任务,没有任务优先级,所以互斥信号量只能用与任务中,不能用于中断服务函数。
- 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。
互斥信号量除了创建函数之外,其余的获取、释放等信号量操作函数,都与二值信号量相同
创建
xSemaphoreCreateMutex() 使用动态方式创建互斥信号量
xSemaphoreCreateMutexStatic() 使用静态方式创建互斥信号量
获取
xSemaphoreTake() 获取信号量
释放
xSemaphoreGive() 释放信号量
删除
vSemaphoreDelete() 删除信号量
内容参考:正点原子《FreeRTOS开发指南》