一、递归锁
/* 创建一个递归锁,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void );/* 释放 */
BaseType_t xSemaphoreGiveRecursive( SemaphoreHandle_t xSemaphore );/* 获得 */
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait
);
static void vTakeTask( void *pvParameters )
{const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL ); BaseType_t xStatus;int i;/* 无限循环 */for( ;; ){ /* 获得递归锁: 上锁 */xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);//上锁成功printf("Task1 take the Mutex in main loop %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");/* 阻塞很长时间, 让另一个任务执行, * 看看它有无办法再次获得递归锁 */vTaskDelay(xTicksToWait);//任务一挂起,任务二就绪运行for (i = 0; i < 10; i++){/* 获得递归锁: 上锁 */xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);printf("Task1 take the Mutex in sub loop %s, for time %d\r\n", \(xStatus == pdTRUE)? "Success" : "Failed", i);/* 释放递归锁 */xSemaphoreGiveRecursive(xMutex);}/* 释放递归锁 */xSemaphoreGiveRecursive(xMutex);}
}
static void vGiveAndTakeTask( void *pvParameters )
{const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL ); BaseType_t xStatus;/* 尝试获得递归锁: 上锁 */xStatus = xSemaphoreTakeRecursive(xMutex, 0);//任务一上锁了,任务二上锁失败//0说明不会等,上锁失败直接返回// xMutex = xSemaphoreCreateRecursiveMutex( );同一把锁printf("Task2: at first, take the Mutex %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");/* 如果失败则监守自盗: 开锁 */if (xStatus != pdTRUE){/* 无法释放别人持有的锁 */xStatus = xSemaphoreGiveRecursive(xMutex);//解锁别人创建的锁失败printf("Task2: give Mutex %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");}printf("task2\r\n");/* 如果无法获得, 一直等待 */xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);//任务二一直堵在这,下不去了//xStatus = xSemaphoreTakeRecursive(xMutex, 0);//改成0就能运行下去printf("Task2: and then, take the Mutex %s\r\n", \(xStatus == pdTRUE)? "Success" : "Failed");/* 无限循环 */for( ;; ){ /* 什么都不做 */vTaskDelay(xTicksToWait);}
}
main函数:
/* 递归锁句柄 */
SemaphoreHandle_t xMutex;int main( void )
{prvSetupHardware();/* 创建递归锁 */xMutex = xSemaphoreCreateRecursiveMutex( );if( xMutex != NULL ){/* 创建2个任务: 一个上锁, 另一个自己监守自盗(开别人的锁自己用)*/xTaskCreate( vTakeTask, "Task1", 1000, NULL, 2, NULL );xTaskCreate( vGiveAndTakeTask, "Task2", 1000, NULL, 1, NULL );/* 启动调度器 */vTaskStartScheduler();}else{/* 无法创建递归锁 */}/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */return 0;
}
A:任务1优先级最高,先运行,获得递归锁
B:任务1阻塞,让任务2得以运行
C:任务2运行,看看能否获得别人持有的递归锁:不能
D:任务2故意执行"give"操作,看看能否释放别人持有的递归锁:不能
E:任务2等待递归锁
F:任务1阻塞时间到后继续运行,使用循环多次获得、释放递归锁
递归锁在代码上实现了:谁持有递归锁,必须由谁释放。