FreeRTOS互斥锁

本文介绍了互斥锁在多任务并发中的作用,包括为何需要互斥锁、互斥锁的工作原理以及如何使用。特别关注了递归互斥锁的出现背景、创建和使用方法,以避免死锁问题。重点讲解了在FreeRTOS中的应用。
摘要由CSDN通过智能技术生成

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);	// 解锁
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS 互斥锁(Mutex)可以用来保护共享资源,以避免多个任务同时访问该资源而导致的数据竞争。 在 FreeRTOS 中,互斥锁是通过 xSemaphoreCreateMutex 函数创建的。该函数返回一个 SemaphoreHandle_t 类型的句柄,表示创建的互斥锁。 使用互斥锁时,需要先通过 xSemaphoreTake 函数获取互斥锁,然后对共享资源进行操作,并在操作完成后通过 xSemaphoreGive 函数释放互斥锁。这样可以确保在任何时刻只有一个任务能够访问共享资源。 下面是一个简单的示例代码,演示了如何使用 FreeRTOS 互斥锁来保护共享资源: ```c SemaphoreHandle_t xMutex; void task1(void *params) { while (true) { // 获取互斥锁 xSemaphoreTake(xMutex, portMAX_DELAY); // 访问共享资源 shared_resource++; // 释放互斥锁 xSemaphoreGive(xMutex); vTaskDelay(1000 / portTICK_PERIOD_MS); } } void task2(void *params) { while (true) { // 获取互斥锁 xSemaphoreTake(xMutex, portMAX_DELAY); // 访问共享资源 shared_resource--; // 释放互斥锁 xSemaphoreGive(xMutex); vTaskDelay(1000 / portTICK_PERIOD_MS); } } int main(void) { // 创建互斥锁 xMutex = xSemaphoreCreateMutex(); // 创建任务 xTaskCreate(task1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); xTaskCreate(task2, "Task2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); // 启动调度器 vTaskStartScheduler(); return 0; } ``` 在上面的示例中,共享资源是一个变量 shared_resource,两个任务分别对其进行加一和减一操作。通过使用互斥锁来保护共享资源,可以确保两个任务不会同时访问该变量,避免了数据竞争的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值