中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

電影日記網(wǎng)站怎么做界首網(wǎng)站優(yōu)化公司

電影日記網(wǎng)站怎么做,界首網(wǎng)站優(yōu)化公司,wordpress 推送到百度,做計算機題目的網(wǎng)站互斥量概述 在博文“ FreeRTOS_信號量 ”中,使用了二進制信號量實現(xiàn)了互斥,保護了串口資源。博文鏈接如下: FreeRTOS_信號量-CSDN博客 但還是要引入互斥量的概念?;コ饬颗c二進制信號量相比,能夠多實現(xiàn)如下兩個功能&#xff1a…

互斥量概述

在博文“?FreeRTOS_信號量 ”中,使用了二進制信號量實現(xiàn)了互斥,保護了串口資源。博文鏈接如下:

FreeRTOS_信號量-CSDN博客

但還是要引入互斥量的概念?;コ饬颗c二進制信號量相比,能夠多實現(xiàn)如下兩個功能:

  • 防止優(yōu)先級反轉(zhuǎn)問題
  • 解決遞歸上鎖/解鎖問題

互斥量有兩種:

  • 普通互斥量:具有優(yōu)先級繼承功能,解決優(yōu)先級反轉(zhuǎn)問題
  • 遞歸鎖:具有優(yōu)先級繼承功能、能夠解決遞歸上鎖/解鎖問題、解決誰上鎖誰才能解鎖的問題

優(yōu)先級反轉(zhuǎn)

優(yōu)先級反轉(zhuǎn)問題

假設(shè)任務(wù)A、B、C的優(yōu)先級為1、2、3。在程序開始時,A進行上鎖,之后B運行搶斷的A,之后C運行搶斷了B。在C中,想獲得鎖,但A已經(jīng)上鎖,所以C進入了阻塞,釋放了CPU。這時B繼續(xù)運行,但不解鎖,從而導(dǎo)致C被B搶占,即高優(yōu)先級的任務(wù)是否能繼續(xù)執(zhí)行由低優(yōu)先級的任務(wù)決定。

這種現(xiàn)象稱為優(yōu)先級反轉(zhuǎn)。

優(yōu)先級繼承

使用優(yōu)先級繼承的方法解決優(yōu)先級反轉(zhuǎn)的問題。

在C獲得鎖之后進入阻塞狀態(tài),同時執(zhí)行上鎖的任務(wù)A會繼承C的優(yōu)先級3,從而進行執(zhí)行。當(dāng)A執(zhí)行完解鎖后,A優(yōu)先級的優(yōu)先級變回原來的優(yōu)先級1。之后C獲得鎖,不再阻塞,C繼續(xù)執(zhí)行,執(zhí)行完成之后,B運行。

在低優(yōu)先級任務(wù)上鎖,高優(yōu)先級任務(wù)獲得鎖阻塞之后,低優(yōu)先級任務(wù)繼承高優(yōu)先級任務(wù)的優(yōu)先級的操作叫做優(yōu)先級繼承。

遞歸上鎖/解鎖

遞歸上鎖原因

遞歸上鎖的示例代碼如下:

void fun(){xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);/* 上鎖 *//* 一些功能 */xSemaphoreGive(SemaphoreHandleTest);/* 解鎖 */
}
void Task1(void *param){while(1){xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);/* 上鎖 *//* 一些功能 */fun();xSemaphoreGive(SemaphoreHandleTest);/* 解鎖 */}
}

在上述代碼中,任務(wù)1首先進行了上鎖,之后調(diào)用了fun函數(shù)。在fun函數(shù)中又進行了上鎖,但這時已經(jīng)上鎖,所以就阻塞在了fun函數(shù)中。最終導(dǎo)致Task1無法執(zhí)行完成fun函數(shù),也就無法執(zhí)行解鎖函數(shù),形成死鎖。

遞歸鎖

使用遞歸鎖可以解決上述問題。遞歸鎖的作用是,如果開始時為A來上鎖,那么在上鎖之后,A依舊可以進行調(diào)用上鎖函數(shù)進行上鎖,而不會進入阻塞狀態(tài)。但不管怎樣,上鎖之后都要解鎖,即:上鎖多少次,就要解鎖多少次,上鎖與解鎖一 一配對。

除此之外,遞歸鎖還可以滿足誰上鎖,誰才有權(quán)力解鎖的問題。而信號量和普通互斥鎖并不能實現(xiàn)這個功能。

相關(guān)配置

在使用互斥量之前,需要打開宏開關(guān),具體的步驟如下:

在使用遞歸鎖之前,需要打開宏開關(guān),具體的步驟如下:

互斥量相關(guān)函數(shù)

創(chuàng)建普通互斥量

函數(shù)聲明如下:

/* 這是一個宏,創(chuàng)建普通互斥量 */
xSemaphoreCreateMutex()/* 宏定義 */
#define xSemaphoreCreateMutex()    xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )/* 實際調(diào)用函數(shù) */
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )

返回值:互斥量的句柄

互斥量在創(chuàng)建后與二進制信號量不同,互斥量初始值為1,二進制信號量初始值為0

獲取/釋放互斥量

獲取和釋放互斥量所用的函數(shù)與二值信號量的函數(shù)一致。

函數(shù)聲明如下:

/* 這是一個宏,存入(釋放)信號量/互斥量 */
xSemaphoreGive( xSemaphore )/* 這是一個宏,獲取信號量/互斥量 */
xSemaphoreTake( xSemaphore, xBlockTime )

存入函數(shù)返回值:成功返回pdPASS,在當(dāng)前計數(shù)值=最大計數(shù)值時,會存入失敗

xSemaphore :信號量句柄

xBlockTime :阻塞等待時間,portMAX_DELAY為死等

創(chuàng)建遞歸鎖

函數(shù)聲明如下:

/* 這是一個宏,創(chuàng)建遞歸鎖 */
xSemaphoreCreateRecursiveMutex()/* 宏定義 */
#define xSemaphoreCreateRecursiveMutex()  \xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )/* 實際調(diào)用函數(shù) */
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )

返回值:互斥量的句柄

創(chuàng)建后初始值為1

獲取/釋放遞歸鎖

獲取和釋放遞歸鎖的函數(shù)用法與互斥量一致,只是名字有所差別

函數(shù)聲明如下:

/* 這是一個宏,存入(釋放)遞歸鎖 */
xSemaphoreGiveRecursive( xMutex )/* 這是一個宏,獲取遞歸鎖 */
xSemaphoreTakeRecursive( xMutex, xBlockTime )

存入函數(shù)返回值:成功返回pdPASS,在當(dāng)前計數(shù)值=最大計數(shù)值時,會存入失敗

xSemaphore :信號量句柄

xBlockTime :阻塞等待時間,portMAX_DELAY為死等

驗證實驗

1、基本互斥實驗

使用互斥量來確保串口的輸出不被打斷。

與二進制信號量實現(xiàn)該功能相比,代碼方面的差異只在初始化不同,其他代碼都沒有進行修改

二進制信號量實現(xiàn)該功能的初始化代碼如下:

/* 創(chuàng)建二進制信號量,初始值自動設(shè)置為 0 */
SemaphoreHandleTest = xSemaphoreCreateBinary();
/* 讓信號量為1,代表串口資源可用 */
xSemaphoreGive(SemaphoreHandleTest);

互斥量實現(xiàn)該功能的初始化代碼如下:

/* 創(chuàng)建互斥量,初始值自動設(shè)置為 1 */
SemaphoreHandleTest = xSemaphoreCreateMutex();

實驗現(xiàn)象和其他代碼實現(xiàn)與博文“?FreeRTOS_信號量 ”中 “ 驗證實驗 ” 均一致。博文鏈接如下:

FreeRTOS_信號量-CSDN博客

2、優(yōu)先級繼承實驗

根據(jù)本文 “互斥量概述” 中 “?優(yōu)先級反轉(zhuǎn) ”內(nèi)容的描述,來進行編寫代碼。這里使用二進制信號量與互斥量進行運行結(jié)果的對比。

具體的代碼實現(xiàn)如下:

QueueHandle_t SemaphoreHandleTest;
char taskA_flag = 0;
char taskB_flag = 0;
char taskC_flag = 0;
void TaskAFunction(void *param){int i=0;while(1){/* 上鎖 */xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);/* 執(zhí)行一個很長的時間的程序 */taskA_flag = 1;taskB_flag = 0;taskC_flag = 0;for(i=0;i<20;i++){printf("%d,%d,%d",taskA_flag,taskB_flag,taskC_flag);taskA_flag = 1;taskB_flag = 0;taskC_flag = 0;}/* 解鎖 */xSemaphoreGive(SemaphoreHandleTest);}
}
void TaskBFunction(void *param){vTaskDelay(5);/* B先休眠,讓A任務(wù)執(zhí)行 */while(1){/* B一直在執(zhí)行,這會導(dǎo)致如果A優(yōu)先級低于B,則A一直不執(zhí)行 */taskA_flag = 0;taskB_flag = 1;taskC_flag = 0;}
}
void TaskCFunction(void *param){int i=0;vTaskDelay(10);/* C先休眠,讓AB任務(wù)執(zhí)行 */while(1){taskA_flag = 0;taskB_flag = 0;taskC_flag = 1;/* 上鎖 */xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);/* C任務(wù)執(zhí)行一段時間 */for(i=0;i<10;i++){printf("this is taskC\r\n");taskA_flag = 0;taskB_flag = 0;taskC_flag = 1;}/* 解鎖 */xSemaphoreGive(SemaphoreHandleTest);}
}
int main( void )
{TaskHandle_t xHandleTask1;TaskHandle_t xHandleTask2;TaskHandle_t xHandleTask3;prvSetupHardware();SerialPortInit();printf("UART TEST\r\n");/* 創(chuàng)建互斥量,初始值自動設(shè)置為 1 *///SemaphoreHandleTest = xSemaphoreCreateMutex();/* 創(chuàng)建二進制信號量,初始值自動設(shè)置為 0 */SemaphoreHandleTest = xSemaphoreCreateBinary();/* 讓信號量為1,代表資源可用 */xSemaphoreGive(SemaphoreHandleTest);xTaskCreate(TaskAFunction,"TaskA",100,(void*)NULL,1,&xHandleTask1);xTaskCreate(TaskBFunction,"TaskB",100,(void*)NULL,2,&xHandleTask2);xTaskCreate(TaskCFunction,"TaskC",100,(void*)NULL,3,&xHandleTask3);vTaskStartScheduler();return 0;
}

該代碼的主要功能就是利用taskA_flag 、taskB_flag、taskC_flag 這三個標(biāo)志位來判斷當(dāng)前任務(wù)是誰在運行。通過邏輯分析儀顯示出這三個變量的電平來分析搶占關(guān)系。

二值信號量的運行結(jié)果如下:

可以看到,在1 -> 2階段中,BC調(diào)用延時處于阻塞態(tài),因此A運行。在2->3階段中,A運行了一段時間后,B的延時結(jié)束,B開始搶占A進行運行。在2->3階段中,B運行了一段時間后,C的延時結(jié)束,C開始搶占B進行運行。以上是正常的搶占流程。

在C搶占B之后,嘗試獲取信號量,但信號量已經(jīng)被A所獲取,還未進行釋放,因此C進入了阻塞狀態(tài),之后B進行搶占到CPU繼續(xù)執(zhí)行。但B的優(yōu)先級高于A,A不能夠釋放信號量,這樣就導(dǎo)致了C永遠處于阻塞態(tài),只有當(dāng)B釋放CPU,A才能釋放信號量,從而C才可以運行,這樣就產(chǎn)生了優(yōu)先級反轉(zhuǎn)的問題。

互斥量的運行結(jié)果如下:

可以看到,在1 -> 2階段中,BC調(diào)用延時處于阻塞態(tài),因此A運行。在2->3階段中,A運行了一段時間后,B的延時結(jié)束,B開始搶占A進行運行。在2->3階段中,B運行了一段時間后,C的延時結(jié)束,C開始搶占B進行運行。以上是正常的搶占流程。

在C搶占B之后,嘗試獲取互斥量,但互斥量已經(jīng)被A所獲取,還未進行釋放,因此A進行優(yōu)先級的繼承,此時A的優(yōu)先級變成了3,即:4 -> 5階段。在5->6階段中,A的優(yōu)先級為3,執(zhí)行完成打印工作后,對互斥量進行了解鎖,這時任務(wù)A的優(yōu)先級變回原來的優(yōu)先級1,C任務(wù)搶占A開始執(zhí)行。

3、誰上鎖,誰才能解鎖實驗

普通互斥量和二進制信號量并未實現(xiàn)誰上鎖,誰才能解鎖,這里使用普通互斥量與遞歸鎖來進行對比,來驗證遞歸鎖能夠?qū)崿F(xiàn)誰上鎖,誰才能解鎖的功能。

具體代碼實現(xiàn)如下:

QueueHandle_t SemaphoreHandleTest;void PrintFunction(void *param){while(1){//		/* 以下為互斥量測試 */
//		xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);
//		printf("%s",(char*)param);
//		xSemaphoreGive(SemaphoreHandleTest);/* 以下為遞歸鎖測試 */xSemaphoreTakeRecursive(SemaphoreHandleTest,portMAX_DELAY);printf("%s",(char*)param);xSemaphoreGiveRecursive(SemaphoreHandleTest);vTaskDelay(1);}
}
void BreakSemaphoreTask(void *param){vTaskDelay(1);while(1){//		/* 以下為互斥量測試 */
//		while(1){
//			
//			/* 如果獲得不到鎖,就直接往里面放一把鎖 */
//			if(xSemaphoreTake(SemaphoreHandleTest,0) == pdFALSE){
//				xSemaphoreGive(SemaphoreHandleTest);
//			}else{
//				break;
//			}
//		}
//		printf("this is break\r\n");
//		xSemaphoreGive(SemaphoreHandleTest);/* 以下為遞歸鎖測試 */while(1){/* 如果獲得不到鎖,就直接往里面放一把鎖 */if(xSemaphoreTakeRecursive(SemaphoreHandleTest,0) == pdFALSE){xSemaphoreGiveRecursive(SemaphoreHandleTest);}else{break;}}printf("this is break\r\n");xSemaphoreGiveRecursive(SemaphoreHandleTest);vTaskDelay(1);}
}int main( void )
{TaskHandle_t xHandleTask1;TaskHandle_t xHandleTask2;TaskHandle_t xHandleTask3;prvSetupHardware();SerialPortInit();printf("UART TEST\r\n");//	/* 創(chuàng)建互斥量,初始值自動設(shè)置為 1 */
//	SemaphoreHandleTest = xSemaphoreCreateMutex();/* 創(chuàng)建遞歸鎖,初始值自動設(shè)置為 1 */SemaphoreHandleTest = xSemaphoreCreateRecursiveMutex();xTaskCreate(PrintFunction,"TaskA",100,(void*)"this is TaskA\r\n",1,&xHandleTask1);xTaskCreate(PrintFunction,"TaskB",100,(void*)"this is TaskB\r\n",1,&xHandleTask2);xTaskCreate(BreakSemaphoreTask,"TaskC",100,(void*)NULL,1,&xHandleTask3);vTaskStartScheduler();return 0;
}

互斥量的運行結(jié)果如下:

可以看到,打印結(jié)果亂套了。這是因為在A上鎖之后,C任務(wù)去放進去了一把鎖,導(dǎo)致B任務(wù)原來在阻塞,突然獲得了鎖,執(zhí)行了B任務(wù)中的printf。因此互斥量并沒有實現(xiàn)誰上鎖,誰才能夠解鎖的功能。

遞歸鎖的運行結(jié)果如下:

可以看到,打印變得非常正常。這是因為遞歸鎖可以實現(xiàn)誰上鎖,誰才能夠解鎖,因此不能夠再C中解開A的鎖,從而執(zhí)行結(jié)果變得正常。

4、遞歸上鎖實驗

在“?誰上鎖,誰才能解鎖實驗 ”的代碼基礎(chǔ)上進行修改,將打印函數(shù)修改為如下情況:

void PrintFunction(void *param){int i=0;while(1){//		/* 以下為互斥量測試 */
//		xSemaphoreTake(SemaphoreHandleTest,portMAX_DELAY);
//		printf("%s",(char*)param);
//		xSemaphoreGive(SemaphoreHandleTest);/* 以下為遞歸鎖測試 */xSemaphoreTakeRecursive(SemaphoreHandleTest,portMAX_DELAY);for(i=0;i<5;i++){/* 遞歸上鎖,上鎖之后再上一次鎖 */xSemaphoreTakeRecursive(SemaphoreHandleTest,portMAX_DELAY);printf("lock:%i\r\n",i);xSemaphoreGiveRecursive(SemaphoreHandleTest);}printf("%s",(char*)param);xSemaphoreGiveRecursive(SemaphoreHandleTest);vTaskDelay(1);}
}

運行結(jié)果如下:

可以看到lock0~4正常打印,說明并未產(chǎn)生阻塞的情況,遞歸鎖可以遞歸上鎖。

http://www.risenshineclean.com/news/11665.html

相關(guān)文章:

  • 有免費的網(wǎng)址嗎南寧seo專員
  • 做網(wǎng)站造假域名推薦
  • 做論壇網(wǎng)站前段用什么框架好點網(wǎng)絡(luò)廣告的概念
  • 公司網(wǎng)站建設(shè)會計上怎么處理百度產(chǎn)品大全入口
  • 華為公司網(wǎng)站建設(shè)方案網(wǎng)站模板圖片
  • 成立做網(wǎng)站的公司網(wǎng)絡(luò)推廣一個月工資多少
  • 網(wǎng)站開發(fā)推廣招聘官網(wǎng)seo優(yōu)化找哪家做
  • 公司網(wǎng)站上首頁代碼模板互聯(lián)網(wǎng)營銷師是干什么的
  • 企業(yè)網(wǎng)站 asp源碼福州seo服務(wù)
  • 網(wǎng)站建設(shè)的具體過程品牌關(guān)鍵詞排名優(yōu)化怎么做
  • 梧州網(wǎng)站建設(shè)公司企業(yè)營銷推廣方案
  • wordpress管理插件旺道seo推廣系統(tǒng)怎么收費
  • wordpress dux 5.3關(guān)鍵詞推廣優(yōu)化app
  • seo短視頻網(wǎng)頁入口引流在線百度seo一本通
  • 記錄開發(fā)wordpress杭州百度seo
  • 十個最好的網(wǎng)站北京建站公司
  • 蘭州網(wǎng)絡(luò)廣告設(shè)計價格聊石家莊seo
  • h5做商城網(wǎng)站國內(nèi)最近的新聞大事
  • 網(wǎng)站備案主體更換百度提交入口地址在哪
  • 網(wǎng)站內(nèi)如何做內(nèi)部鏈接seo項目優(yōu)化案例分析文檔
  • 上海網(wǎng)站建設(shè)公司 1861webgoogle search
  • 秦皇島網(wǎng)站建設(shè)seo百度指數(shù)平臺
  • 給網(wǎng)站做壓力測試百度一下你就知道官網(wǎng)網(wǎng)址
  • 怎么在工商局網(wǎng)站做注銷蘇州seo關(guān)鍵詞優(yōu)化推廣
  • 免費申請網(wǎng)站官網(wǎng)培訓(xùn)機構(gòu)退費糾紛一般怎么解決
  • 建網(wǎng)站 綁定域名 網(wǎng)址重慶好的seo平臺
  • 企業(yè)制作企業(yè)網(wǎng)站今天發(fā)生的重大新聞內(nèi)容
  • 上海網(wǎng)站建設(shè)-中國互聯(lián)免費模板
  • .net做的大型網(wǎng)站嗎百度搜索排名
  • 優(yōu)秀政府門戶網(wǎng)站b2b平臺有哪幾個