一、计数型信号量简介
有些资料中也将计数型信号量叫做数值信号量,二值信号量相当于长度为1的队列,那么计数型信号量就是长度大于1的队列。**同二值信号量一样,用户不需要关心队列中存储了什么数据,只需要关心队列是否为空即可。**计数型信号量通常用于如下两个场合:
- 1、事件计数
在这个场合中,每次事件发生的时候就在事件处理函数中释放信号量(增加信号量的计数值),其他任务会获取信号量(信号量计数值减一,信号量值就是队列结构体成员变量uxMessagesWaiting)来处理事件。在这种场合中创建的计数型信号量初始计数值为0。 - 2、资源管理
在这个场合中,信号量值代表当前资源的可用数量,比如停车场当前剩余的停车位数量。一个任务要想获得资源的使用权,首先必须获取信号量,信号量获取成功以后信号量值就会减一。当信号量值为0的时候说明没有资源了。当一个任务使用完资源以后一定要释放信号量,释放信号量以后信号量值会加一。在这个场合中创建的计数型信号量初始值应该是资源的数量,比如停车场一共有100个停车位,那么创建信号量的时候信号量值就应该初始化为100。
二、计数型信号量相关API
1、创建计数型信号量API
FreeRTOS提供了两个计数型信号量创建函数,如下表所示:
函数 | 描述 |
---|---|
xSemaphoreCreateCounting() | 使用动态方法创建计数型信号量。 |
xSemaphoreCreateCountingStatic() | 使用静态方法创建计数型信号量 |
- ①、函数xSemaphoreCreateCounting()
此函数用于创建一个计数型信号量,所需要的内存通过动态内存管理方法分配。此函数本质是一个宏,真正完成信号量创建的是函数xQueueCreateCountingSemaphore(),此函数原型如下:
SemaphoreHandle_t xSemaphoreCreateCounting(
UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount)
参数 | 描述 |
---|---|
uxMaxCount | 计数信号量最大计数值,当信号量值等于此值的时候释放信号量就会失败。 |
uxInitialCount | 计数信号量初始值。 |
返回值 | NULL:计数型信号量创建失败。其他值:计数型信号量创建成功,返回计数型信号量句柄。 |
- 2、函数xSemaphoreCreateCountingStatic()
此函数也是用来创建计数型信号量的,使用此函数创建计数型信号量的时候所需要的内存需要由用户分配。此函数也是一个宏,真正执行的是函数xQueueCreateCountingSemaphoreStatic(),
函数原型如下:
SemaphoreHandle_t xSemaphoreCreateCountingStatic(
UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount,
StaticSemaphore_t* pxSemaphoreBuffer)
参数 | 描述 |
---|---|
uxMaxCount | 计数信号量最大计数值,当信号量值等于此值的时候释放信号量就会失败。 |
uxInitialCount | 计数信号量初始值。 |
pxSemaphoreBuffer | 指向一个StaticSemaphore_t类型的变量,用来保存信号量结构体。 |
返回值 | NULL:计数型信号量创建失败。其他值:计数型信号量创建成功,返回计数型信号量句柄。 |
三、计数型信号量创建过程分析
动态创建计数型信号量函数xSemaphoreCreateCounting()此函数是个宏,定义如下:
#if(configSUPPORT_DYNAMIC_ALLOCATION==1)
#define xSemaphoreCreateCounting(uxMaxCount,uxInitialCount) \
xQueueCreateCountingSemaphore((uxMaxCount),(uxInitialCount)) \
#endif
可以看出,真正干事的是函数xQueueCreateCountingSemaphore(),此函数在文件queue.c中有如下定义:
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
{
QueueHandle_t xHandle;
configASSERT( uxMaxCount != 0 );
configASSERT( uxInitialCount <= uxMaxCount );
xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );(1)
if( xHandle != NULL )
{
( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;(2)
traceCREATE_COUNTING_SEMAPHORE();
}
else
{
traceCREATE_COUNTING_SEMAPHORE_FAILED();
}
return xHandle;
}
- (1)、计数型信号量也是在队列的基础上实现的,所以需要调用函数xQueueGenericCreate()创建一个队列,队列长度为uxMaxCount,对列项长度为queueSEMAPHORE_QUEUE_ITEM_LENGTH(此宏为0),队列的类型为queueQUEUE_TYPE_COUNTING_SEMAPHORE,表示是个计数型信号量。
- (2)、队列结构体的成员变量uxMessagesWaiting用于计数型信号量的计数,根据计数型信号量的初始值来设置uxMessagesWaiting。