二值信号量的本质是一个队列长度为1的队列,该队列就只有空和满两种情况,这就是二值。
二值信号量通常用于互斥访问或任务同步,与互斥信号量比较类似,但是二值信号量有可能会导致优先级翻转的问题,所以二值信号量更适合用于同步。
SemaphoreHandle_t xSemaphoreCreateBinary( void );
xSemaphoreTake( SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait );
xSemaphoreTakeFromISR
(
SemaphoreHandle_t xSemaphore,
signed BaseType_t *pxHigherPriorityTaskWoken
)
xSemaphoreGive( SemaphoreHandle_t xSemaphore );
xSemaphoreGiveFromISR
(
SemaphoreHandle_t xSemaphore,
signed BaseType_t *pxHigherPriorityTaskWoken
)
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
重点:在许多使用场景中,使用直达任务通知要比使用二值信号量的速度更快,内存效率更高。所以,没有实例代码。
计数型信号量相当于队列长度大于1的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定的。
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount);
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
其他接口与二值信号量的接口一致。
重点:在许多情况下,任务通知可以提供计数信号量的轻量级替代方案。
互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最合适。互斥信号量适合那些需要互斥访问的应用中。
注意:互斥信号量不能用于中断服务函数中,原因如下:
SemaphoreHandle_t xSemaphoreCreateMutex( void )
xSemaphoreGive( SemaphoreHandle_t xSemaphore );
xSemaphoreTake( SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait );
SemaphoreHandle_t xSemaphore = NULL;
/* A task that creates a semaphore. */
void vATask( void * pvParameters )
{
/* Create the semaphore to guard a shared resource. As we are using
the semaphore for mutual exclusion we create a mutex semaphore
rather than a binary semaphore. */
xSemaphore = xSemaphoreCreateMutex();
}
/* A task that uses the semaphore. */
void vAnotherTask( void * pvParameters )
{
/* ... Do other things. */
if( xSemaphore != NULL )
{
/* See if we can obtain the semaphore. If the semaphore is not
available wait 10 ticks to see if it becomes free. */
if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
{
/* We were able to obtain the semaphore and can now access the
shared resource. */
/* ... */
/* We have finished accessing the shared resource. Release the
semaphore. */
xSemaphoreGive( xSemaphore );
}
else
{
/* We could not obtain the semaphore and can therefore not access
the shared resource safely. */
}
}
}
xSemaphoreCreateMutex()用于创建非递归互斥锁。非递归互斥锁只能被一个任务 获取一次,如果同一个任务想再次获取则会失败, 因为当任务第一次释放互斥锁时,互斥锁就一直 处于释放状态。
与非递归互斥锁相反,递归互斥锁可以被同一个任务获取很多次, 获取多少次就需要释放多少次, 此时才会返回递归互斥锁。
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
xSemaphoreTakeRecursive( SemaphoreHandle_t xMutex,
TickType_t xTicksToWait );
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )