C語言 Freertos的遞歸鎖詳解
1.死鎖的概念
假設(shè)有 2 個(gè)互斥量 M1、 M2, 2 個(gè)任務(wù) A、 B: A 獲得了互斥量 M1 B 獲得了互斥量 M2 A 還要獲得互斥量 M2 才能運(yùn)行,結(jié)果 A 阻塞 B 還要獲得互斥量 M1 才能運(yùn)行,結(jié)果 B 阻塞 A、 B 都阻塞,再無法釋放它們持有的互斥量 死鎖發(fā)生!
2.自我死鎖
任務(wù) A 獲得了互斥鎖 M 它調(diào)用一個(gè)函數(shù) 函數(shù)要去獲取同一個(gè)互斥鎖 M,于是它阻塞:任務(wù) A 休眠,等待任務(wù) A 來釋放互斥鎖! 死鎖發(fā)生!
3.遞歸鎖
1.任務(wù) A 獲得遞歸鎖 M 后,它還可以多次去獲得這個(gè)鎖
2."take"了 N 次,要"give"N 次,這個(gè)鎖才會被釋放
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個(gè)任務(wù): 一個(gè)上鎖, 另一個(gè)自己監(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"); /* 阻塞很長時(shí)間, 讓另一個(gè)任務(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.運(yùn)行流程分析
1.任務(wù) 1 優(yōu)先級最高,先運(yùn)行,獲得遞歸鎖
2.任務(wù) 1 阻塞,讓任務(wù) 2 得以運(yùn)行
3.任務(wù) 2 運(yùn)行,看看能否獲得別人持有的遞歸鎖: 不能
4.任務(wù) 2 故意執(zhí)行"give"操作,看看能否釋放別人持有的遞歸鎖:不能
5.任務(wù) 2 等待遞歸鎖
6.任務(wù) 1 阻塞時(shí)間到后繼續(xù)運(yùn)行,使用循環(huán)多次獲得、釋放遞歸鎖
6.運(yùn)行結(jié)果
總結(jié)
誰持有遞歸鎖,必須由誰釋放。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
項(xiàng)目之C++如何實(shí)現(xiàn)數(shù)據(jù)庫連接池
這篇文章主要介紹了項(xiàng)目之C++如何實(shí)現(xiàn)數(shù)據(jù)庫連接池問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03C++通過循環(huán)實(shí)現(xiàn)猜數(shù)字小游戲
這篇文章主要為大家詳細(xì)介紹了C++通過循環(huán)實(shí)現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09C++面向行輸入之get()與getline()實(shí)例詳解
在c++里當(dāng)我們輸入一個(gè)字符串時(shí)習(xí)慣用cin,但是cin只能讀取一段不含空格的字符串,如果我們需要讀取一段包含空格的字符串時(shí),就需要用到getline()或get(),下面這篇文章主要給大家介紹了關(guān)于C++面向行輸入之get()與getline()的相關(guān)資料,需要的朋友可以參考下2021-10-10