C語言 Freertos的遞歸鎖詳解
1.死鎖的概念
假設(shè)有 2 個互斥量 M1、 M2, 2 個任務(wù) A、 B: A 獲得了互斥量 M1 B 獲得了互斥量 M2 A 還要獲得互斥量 M2 才能運行,結(jié)果 A 阻塞 B 還要獲得互斥量 M1 才能運行,結(jié)果 B 阻塞 A、 B 都阻塞,再無法釋放它們持有的互斥量 死鎖發(fā)生!
2.自我死鎖
任務(wù) A 獲得了互斥鎖 M 它調(diào)用一個函數(shù) 函數(shù)要去獲取同一個互斥鎖 M,于是它阻塞:任務(wù) A 休眠,等待任務(wù) A 來釋放互斥鎖! 死鎖發(fā)生!
3.遞歸鎖
1.任務(wù) A 獲得遞歸鎖 M 后,它還可以多次去獲得這個鎖
2."take"了 N 次,要"give"N 次,這個鎖才會被釋放
3.誰上鎖就由誰解鎖。
遞歸鎖的函數(shù)根一般互斥量的函數(shù)名不一樣
遞歸鎖 | 一般互斥量 | |
---|---|---|
創(chuàng)建 | xSemaphoreCreateRecursive Mutex | xSemaphoreCreateMutex |
獲得 | xSemaphoreTakeRecursive | xSemaphoreTake |
釋放 | xSemaphoreGiveRecursive | xSemaphoreGive |
4.代碼
main
/* 遞歸鎖句柄 */ SemaphoreHandle_t xMutex; int main( void ) { prvSetupHardware(); /* 創(chuàng)建遞歸鎖 */ xMutex = xSemaphoreCreateRecursiveMutex( ); if( xMutex != NULL ) { /* 創(chuàng)建2個任務(wù): 一個上鎖, 另一個自己監(jiān)守自盜(開別人的鎖自己用) xTaskCreate( vTakeTask, "Task1", 1000, NULL, 2, NULL ); xTaskCreate( vGiveAndTakeTask, "Task2", 1000, NULL, 1, NULL ); /* 啟動調(diào)度器 */ vTaskStartScheduler(); } else { /* 無法創(chuàng)建遞歸鎖 */ } return 0; }
任務(wù)1
static void vTakeTask( void *pvParameters ) { const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL ); BaseType_t xStatus; int i; /* 無限循環(huán) */ for( ;; ) { /* 獲得遞歸鎖: 上鎖 */ xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY); printf("Task1 take the Mutex in main loop %s\r\n", \ (xStatus == pdTRUE)? "Success" : "Failed"); /* 阻塞很長時間, 讓另一個任務(wù)執(zhí)行, * 看看它有無辦法再次獲得遞歸鎖 */ 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); } }
任務(wù)2
static void vGiveAndTakeTask( void *pvParameters ) { const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL ); BaseType_t xStatus; /* 嘗試獲得遞歸鎖: 上鎖 */ xStatus = xSemaphoreTakeRecursive(xMutex, 0); printf("Task2: at first, take the Mutex %s\r\n", \ (xStatus == pdTRUE)? "Success" : "Failed"); /* 如果失敗則監(jiān)守自盜: 開鎖 */ if (xStatus != pdTRUE) { /* 無法釋放別人持有的鎖 */ xStatus = xSemaphoreGiveRecursive(xMutex); printf("Task2: give Mutex %s\r\n", \ (xStatus == pdTRUE)? "Success" : "Failed"); } /* 如果無法獲得, 一直等待 */ xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY); printf("Task2: and then, take the Mutex %s\r\n", \ (xStatus == pdTRUE)? "Success" : "Failed"); /* 無限循環(huán) */ for( ;; ) { /* 什么都不做 */ vTaskDelay(xTicksToWait); } }
5.運行流程分析
1.任務(wù) 1 優(yōu)先級最高,先運行,獲得遞歸鎖
2.任務(wù) 1 阻塞,讓任務(wù) 2 得以運行
3.任務(wù) 2 運行,看看能否獲得別人持有的遞歸鎖: 不能
4.任務(wù) 2 故意執(zhí)行"give"操作,看看能否釋放別人持有的遞歸鎖:不能
5.任務(wù) 2 等待遞歸鎖
6.任務(wù) 1 阻塞時間到后繼續(xù)運行,使用循環(huán)多次獲得、釋放遞歸鎖
6.運行結(jié)果
總結(jié)
誰持有遞歸鎖,必須由誰釋放。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
項目之C++如何實現(xiàn)數(shù)據(jù)庫連接池
這篇文章主要介紹了項目之C++如何實現(xiàn)數(shù)據(jù)庫連接池問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03C++通過循環(huán)實現(xiàn)猜數(shù)字小游戲
這篇文章主要為大家詳細介紹了C++通過循環(huán)實現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-09-09