信息量
简介
特点
1、当计数值大于0,代表有信号量资源。
2、当释放信号量,信号量计数值(资源数)加一。
3、当获取信号量,信号量计数值(资源数)减一。
4、信号量:用于传递状态。
5、当信号量如果最大值被限定为1,那么它就是二值信号量;如果最大值不是1,它就是计数型信号量。
二进制信号量跟计数型信号量的区别
二进制信号量跟计数型的唯一差别,就是计数值的最大值被限定为1。
信号量跟队列的对比
这里的生产者指的是give信号量的任务,消费者是take信号量的任务。
信号量函数
创建
创建二进制信号量的函数原型如下:
/* 创建一个二进制信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinary( void );
/* 创建一个二进制信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的指
针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffe
r );
创建计数型信号量的函数原型如下:
/* 创建一个计数型信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* uxMaxCount: 最大计数值
* uxInitialCount: 初始计数值
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t ux
InitialCount);
/* 创建一个计数型信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的指
针
* uxMaxCount: 最大计数值
* uxInitialCount: 初始计数值
* pxSemaphoreBuffer: StaticSemaphore_t 结构体指针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount,
StaticSemaphore_t *pxSemaphoreBuffer );
删除
对于动态创建的信号量,不再需要它们时,可以删除它们以回收内存。
vSemaphoreDelete 可以用来删除二进制信号量、计数型信号量,函数原型如下:
/*
* xSemaphore: 信号量句柄,你要删除哪个信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
获取信号量当前计数值大小
uxSemaphoreGetCount( xSemaphore);
返回值:计数值。参数:信号量的句柄。
give/take
xSemaphoreGive 的函数原型如下:
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
xSemaphoreGiveFromISR 函数的参数与返回值列表如下:
BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken);
xSemaphoreTake 函数的参数与返回值列表如下 :
xSemaphoreTakeFromISR 的函数原型如下:
BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken);
这里有一点需要读者留意,ISR函数里面有一个BaseType_t*pxHigherPriorityTaskWoken ,和相对另一个参数TickType_t xTicksToWait却不一样,这里是因为,在中断里面调用take ,因为中断无法被阻塞,我们不能设置需要等待的tick,我们会设置这个参数,来告诉是否有任务因为中断读取信号量而变成了就绪态,之后根据这个值,决定是否进行任务调度,去切换任务。
主要作用:优先级翻转
互斥量
简介
互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中!
优先级继承
互斥量的使用场合
互斥量函数
创建
使用互斥量时,先创建、然后去获得、释放它。使用句柄来表示一个互斥量。 创建互斥量的函数有2种:动态分配内存,静态分配内存,函数原型如下:
动态分配内存:
/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );
静态分配内存:
/* 创建一个互斥量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的
指针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
要想使用互斥量,需要在配置文件FreeRTOSConfig.h中定义:#define configUSE_MUTEXES 1
删除
/*
* xSemaphore: 信号量句柄,你要删除哪个信号量, 互斥量也是一种信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
释放
获得
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
互斥量不能在ISR中使用
xSemaphoreGiveFromISR
和
xSemaphoreTakeFromISR
,这些函数经过设计以确保在 ISR 上下文中操作信号量的安全性和有效性。这些函数在实现上会考虑到互斥量的特殊性和需求。
总结
信号量:
信号量就是特殊的队列。
队列里使用环形缓冲区存放数据,
信号量里只记录计数值。
互斥量:
互斥量就是特殊的队列。
互斥量更是特殊的信号量,
互斥量实现了优先级继承。
至于信号量和互斥量的内部机制,我们可以知道,他们都是特殊的队列,实际上和队列的内部机制几乎一样,如果想要了解,可以去看我FreeRTOS消息队列,里面有队列的内部机制讲解。