目录
一、二值信号量
1、简介
二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问,有关互斥信号量的内容后面会专门讲解,本节只讲解二值信号量在同步中的应用。
二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空的
2、二值信号量的创建
-
动态创建二值信号量
SemaphoreHandle xSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore );
注意:在旧版本中,使用vSemaphoreCreateBinary ();
该函数是一个宏,最终调用的是
QueueHandle_t xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );
意为创建了一个长度为1的队列
返回值类型SemaphoreHandle QueueHandle_t为一种类型在semphr.h中,79行:
typedef QueueHandle_t SemaphoreHandle_t;
-
参数
无
-
返回值
创建成功返回二值信号量句柄,失败返回NULL
-
静态创建二值信号量
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( uint8_t *pxStaticSemaphore );
3、二值信号量的释放
xSemaphoreGive();
4、二值信号量的获取
xSemaphoreTake();
二、计数型信号量
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount );
-
参数
uxMaxCount: 计数信号量最大计数值,当信号量值等于此值的时候释放信号量就会失败。
-
返回值
NULL: 计数型信号量创建失败。
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount,
StaticSemaphore_t * pxSemaphoreBuffer );
-
参数
-
返回值
三、优先级翻转现象
这个现象一般出现在使用二值信号量时出现,当优先级低的任务先获取了信号量时,高优先级任务即使抢占了低优先级任务的cpu使用权,也会阻塞,把cpu使用权交给低优先级的任务,中优先级的任务同样可以抢占低优先级,使得二值信号量始终不能得到释放,导致高优先级任务迟迟不能执行,反而低优先级的任务优先执行,后面学到互斥量可以解决此问题。
有一个资源,高优先级和低优先级都需要使用到,当高的不用时,顺利低的就使用上了,但是在低的使用过程中,可能会被中等优先级的任务抢占,导致低优先级的任务占了这个资源,却不能执行,因为中优先级要用cpu,但是,这个时候,高优先级的任务突然抢占了中优先级任务且需要这个资源了,就会发现低任务优先级占用了资源,却不能执行完释放,这就把高优先级阻塞了。
知识点(注释): 1、在使用二值信号量时 引入的头文件是"semphr.h" 不是"queue.h" 2、在移植正点原子延时函数时 要注释掉it.c中的void SysTick_Handler(void) 因为在delay.c中重写过了
优先级翻转是个很严重的问题,那么有没有解决方法呢?有!这就要引出另外一种信号量——互斥信号量!
三、互斥信号量
1、功能
当一个互斥信号量正在被一个低优先级的任务使用,而此时有个高优先级的任务也尝试获取这个互斥信号量的话就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级 提升 到与自己相同的优先级,这个过程就是
优先级继承。优先级继承尽可能的降低了高优先级任务处于阻塞态的时间,并且将已经出现的“优先级翻转”的影响降到最低。
2、动态创建函数
SemaphoreHandle_t xSemaphoreCreateMutex( void );
-
参数
无
-
返回值
成功返回信号量句柄,失败返回NULL
3、静态创建函数
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
-
参数
pxMutexBuffer:此参数指向一个 StaticSemaphore_t 类型的变量,用来保存信号量结构体。
-
返回值
成功返回信号量句柄,失败返回NULL
4、获取互斥信号量
xSemaphoreGive()
5、释放互斥信号量
xSemaphoreTake()
递归互斥信号量
相当于一个可以多次获取的互斥信号量,已经获取了递归互斥信号量的任务可以再次获取这个递归互斥信号量,而且次数不限!一个任务使用函数xSemaphoreTakeRecursive()成功的获取了多少次递归互斥信号量就得使用函数 xSemaphoreGiveRecursive()释放多少次。
-
要使用递归互斥信号量的话宏 configUSE_RECURSIVE_MUTEXES 必须为 1!
创建函数
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
-
返回值
NULL:创建失败。
其他值 :创建成功的互斥信号量的句柄。
释放函数
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex);//该函数是一个宏定义 BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex );//起作用的是这个函数
获取函数
BaseType_t xSemaphoreTakeRecursive( SemaphoreHandle_t xMutex, TickType_t xTicksToWait );//该函数是一个宏定义 BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, //要获取的信号量 TickType_t xTicksToWait )//阻塞时间