这里写目录标题
1、为什么会有互斥锁
对于多个任务同时争抢同一个资源是(比如两个任务同时使用同一个串口),简单的办法是使用临界区来解决,但是频繁使用临界区会严重拖累系统的运转,也就是对RTOS实时性的破坏,因为使用临界区的本质是关掉Tick中断。有没有更好的方法来解决临界资源的问题呢?这个时候就要引入互斥锁了。
2、什么是互斥锁
拿电脑中文档举例:当一个文档已经被打开,这时如果再双击打开这个文档,则会提示“操作无法完成,因为文件已在word软件中打开”。这是因为操作系统在第一次打开文件的时候,给文件设置了一把锁。而如果后面还有程序想要操作文件,则因为上锁的原因,打开失败。避免暂停系统运转,纯逻辑层面解决了临界资源争抢的问题。另外还能解决优先级反转的问题
锁的机制:资源我正在用,已经上锁,我什么时候解锁,你什么时候用。
上锁:防止随意访问
解锁:有权访问
3、如何使用互斥锁
3.1、创建互斥锁
// 定义互斥锁
SemaphoreHandle_t MutexSemaphore;
// 创建互斥锁
MutexSemaphore = xSemaphoreCreateMutex();
3.2、上锁
上锁和接受信号量是一个函数
xSemaphoreTake(MutexSemaphore, portMAX_DELAY);
3.3、解锁
解锁和释放信号量是一个函数
xSemaphoreGive(MutexSemaphore);
4、递归互斥锁
4.1、为什么会有递归互斥锁
死锁:A代码已经将文件上锁了,让B去读取文件,B代码也将文件上锁,发现锁已经被A用了,造成相互死锁。这个时候就要引出递归互斥锁了。如下面的代码,print1任务1刚开始拿MutexSemaphore进行上锁,但在调用myfun()函数时发现,myfun()也要用MutexSemaphore进行上锁,print1任务1还没解锁,myfun()函数又需要MutexSemaphore进行上锁,这就导致了死锁。为了防止死锁现象,RTOS发明了递归互斥锁。
// 任务1 打印信息1
void print1(void *p)
{
while(1)
{
xSemaphoreTakeRecursive(MutexSemaphore, portMAX_DELAY); // 上锁
myfun();
xSemaphoreGiveRecursive(MutexSemaphore); // 解锁
}
}
void myfun(void)
{
xSemaphoreTakeRecursive(MutexSemaphore, portMAX_DELAY); // 上锁
printf("data process complete!\r\n");
xSemaphoreGiveRecursive(MutexSemaphore); // 解锁
}
4.2 、如何创建递归互斥锁
在FreeRTOS.h中将configUSE_RECURSIVE_MUTEXES宏置为1
// 创建递归互斥锁
MutexSemaphore = xSemaphoreCreateRecursiveMutex();
4.3 、如何上锁和解锁递归互斥锁
xSemaphoreTakeRecursive(MutexSemaphore, portMAX_DELAY); // 上锁
myfun();
xSemaphoreGiveRecursive(MutexSemaphore); // 解锁