C語(yǔ)言 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è)鎖才會(huì)被釋放
3.誰(shuí)上鎖就由誰(shuí)解鎖。
遞歸鎖的函數(shù)根一般互斥量的函數(shù)名不一樣
| 遞歸鎖 | 一般互斥量 | |
|---|---|---|
| 創(chuàng)建 | xSemaphoreCreateRecursiveMutex | 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 );
/* 啟動(dòng)調(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");
/* 阻塞很長(zhǎng)時(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)先級(jí)最高,先運(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é)
誰(shuí)持有遞歸鎖,必須由誰(shuí)釋放。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
詳解C語(yǔ)言內(nèi)核中的鏈表與結(jié)構(gòu)體
Windows內(nèi)核中是無法使用vector容器等數(shù)據(jù)結(jié)構(gòu)的,當(dāng)我們需要保存一個(gè)結(jié)構(gòu)體數(shù)組時(shí),就需要使用內(nèi)核中提供的專用鏈表結(jié)構(gòu)。本文分享了幾個(gè)內(nèi)核中使用鏈表存儲(chǔ)多個(gè)結(jié)構(gòu)體的通用案例,希望對(duì)你有所幫助2022-09-09
基于Qt實(shí)現(xiàn)C/C++調(diào)用Matlab函數(shù)全過程
這篇文章給大家詳細(xì)介紹了基于Qt平臺(tái)實(shí)現(xiàn)C/C++調(diào)用Matlab函數(shù)全流程,文中通過圖文和代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-01-01
VC中CWinThread類以及和createthread API的區(qū)別分析
這篇文章主要介紹了VC中CWinThread類以及和createthread API的區(qū)別分析,較為詳細(xì)的講述了CWinThread類的原理,并以實(shí)例形式對(duì)AfxBeginThread函數(shù)的內(nèi)部實(shí)現(xiàn)進(jìn)行了解釋說明,需要的朋友可以參考下2014-10-10
C語(yǔ)言循環(huán)隊(duì)列的表示與實(shí)現(xiàn)實(shí)例詳解
這篇文章主要介紹了C語(yǔ)言循環(huán)隊(duì)列的表示與實(shí)現(xiàn),對(duì)于數(shù)據(jù)結(jié)構(gòu)與算法的研究很有幫助,需要的朋友可以參考下2014-07-07
C++ STL 內(nèi) std::{bind/tuple/function} 簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了C++ STL 內(nèi) std::{bind/tuple/function} 簡(jiǎn)單實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
C++中高性能內(nèi)存池的實(shí)現(xiàn)詳解
在 C/C++ 中,內(nèi)存管理是一個(gè)非常棘手的問題,我們?cè)诰帉懸粋€(gè)程序的時(shí)候幾乎不可避免的要遇到內(nèi)存的分配邏輯。本文將通過C++實(shí)現(xiàn)高性能內(nèi)存池,感興趣的可以了解一下2022-10-10
C++?OpenCV實(shí)現(xiàn)物體尺寸測(cè)量示例詳解
本文主要介紹了利用OpenCV對(duì)物體的尺寸進(jìn)行測(cè)量,即先定位到待測(cè)物體的位置,然后測(cè)量物體的寬高。感興趣的同學(xué)可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)2022-01-01
C++強(qiáng)制轉(zhuǎn)換與智能指針示例詳解
這篇文章主要介紹了C++強(qiáng)制轉(zhuǎn)換與智能指針示例,智能指針(Smart Pointer)是一種抽象的數(shù)據(jù)類型。在程序設(shè)計(jì)中,它通常是經(jīng)由類模板來實(shí)現(xiàn),借由模板來達(dá)成泛型,借由類別的析構(gòu)函數(shù)來達(dá)成自動(dòng)釋放指針?biāo)赶虻拇鎯?chǔ)器或?qū)ο?/div> 2022-11-11最新評(píng)論

