文章目录
是什么?
本质就是队列,但是没有读写操作,有最大值和计数,还有receiver的等待链表,没有send链表,接收放不能通过send链表去唤醒发送方,因为信号量有就发给你,没有就没有了;
信号量唤醒的顺序问题:
二进制信号量的初始值为0;
计数型信号量的初始值可以设置;
信号量的receive_list链表;
未take到拿到信号的任务,都存在链表中等待;
优先级反转
优先级高的任务无法去打断优先级低的任务;
task2,无需信号量可以直接执行,delay(1000),1s后运行;
现在task2,经过1s的阻塞,优先级高,所以打断task1,而且运行到最后没有删除任务的函数,所以接下来会一直运行task2,task1假设打断前没运行完,没give掉信号量,那永远占着信号量不释放给task3;
最终导致task3任务优先级最高却无法运行;
如何解决优先级反转的问题?
互斥量只是特殊的信号量;
函数的使用方法和信号量完全一样;
使用互斥量来解决优先级反转
互斥量创建后计数值会提升为1
使用互斥量、task3任务启动时会将正在执行的task1任务的优先级提升到与自己相同,等待task1任务执行完成后task3立即运行,task1执行完成后优先级变回原来;
使用互斥量
/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );
/* 创建一个互斥量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );
不管是队列、信号量、互斥量、创建方式和使用方式一样的;
解决I2C互斥访问问题
用全局变量来当互斥量是由隐患的:
比如任务2运行到函数LCD_FlushRegion,全局变量bInUsed已经被置位1,此时任务3创建,优先级高于任务2,开始运行,到while(bInUsed),bInUsed只要任务2不给他置位0,那么任务3的while(bInUsed)会永远卡住;
改进
在初始化的函数中创建出来(略)
递归锁
互斥量,无法实现谁take谁give;
使用递归,只能是take的任务去give(只能是拥有者开锁,其他人开不了锁);
需要配置一个变量才能用递归锁