content_views"
c lass="markdown_views prism-atom-one-light">
cap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-bloc k" style="-webkit-tap-highlight-c olor: rgba(0, 0, 0, 0);">
前言
通过学习上一章互斥量理论基础c ;这一章我们来做一些实验进行验证。
一、互斥量与二进制信号量
ckquote> 互斥量使用和二进制信号量类似
ckquote>
互斥量有优先级继承 功能c ;二进制信号量没有 Give/Take函数完全一样 二进制信号量的初始值 是0c ;互斥量的初始值是1
二、优先级反转与优先级继承
ckquote> 首先创建三个优先级不同的任务
ckquote>
<c ode c lass="prism language-c pp"> class="token func tion">xTaskCreate class="token punc tuation">( vLPTaskclass="token punc tuation">, class="token string">"LPTask" class="token punc tuation">, class="token number">1000 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">, class="token number">1 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">) class="token punc tuation">; class="token func tion">xTaskCreate class="token punc tuation">( vMPTaskclass="token punc tuation">, class="token string">"MPTask" class="token punc tuation">, class="token number">1000 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">, class="token number">2 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">) class="token punc tuation">; class="token func tion">xTaskCreate class="token punc tuation">( vHPTaskclass="token punc tuation">, class="token string">"HPTask" class="token punc tuation">, class="token number">1000 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">, class="token number">3 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">) class="token punc tuation">;
c ode>
ckquote> 创建互斥量/二进制信号量
ckquote>
<c ode c lass="prism language-c pp">SemaphoreHandle_t xLoc kclass="token punc tuation">;
class="token c omment">// xLoc k = xSemaphoreCreateBinary( ); xLoc k class="token operator">= class="token func tion">xSemaphoreCreateMutex class="token punc tuation">( class="token punc tuation">) class="token punc tuation">; class="token func tion">xSemaphoreGive class="token punc tuation">( xLoc kclass="token punc tuation">) class="token punc tuation">;
c ode>
ckquote> 三个优先级不同的任务处理不同事情c ;验证二进制信号量 的优先级反转 和互斥量 的优先级继承 功能
ckquote>
<c ode c lass="prism language-c pp">class="token c omment">/*-----------------------------------------------------------*/
class="token keyword">static class="token keyword">void class="token func tion">vLPTask class="token punc tuation">( class="token keyword">void class="token operator">* pvParameters class="token punc tuation">)
class="token punc tuation">{ class="token keyword">c onst Tic kType_t xTic ksToWait class="token operator">= class="token func tion">pdMS_TO_TICKS class="token punc tuation">( class="token number">10UL class="token punc tuation">) class="token punc tuation">; class="token keyword">uint32_t iclass="token punc tuation">; class="token keyword">c har c class="token operator">= class="token c har">'A' class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"LPTask start\r\n" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 无限循环 */ class="token keyword">for class="token punc tuation">( class="token punc tuation">; class="token punc tuation">; class="token punc tuation">) class="token punc tuation">{ flagLPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; class="token c omment">/* 获得互斥量/二进制信号量 */ class="token func tion">xSemaphoreTake class="token punc tuation">( xLoc kclass="token punc tuation">, portMAX_DELAYclass="token punc tuation">) class="token punc tuation">; class="token c omment">/* 耗时很久 */ class="token func tion">printf class="token punc tuation">( class="token string">"LPTask take the Loc k for long time" class="token punc tuation">) class="token punc tuation">; class="token keyword">for class="token punc tuation">( i class="token operator">= class="token number">0 class="token punc tuation">; i class="token operator">< class="token number">26 class="token punc tuation">; iclass="token operator">++ class="token punc tuation">) class="token punc tuation">{ flagLPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"%c " class="token punc tuation">, c class="token operator">+ iclass="token punc tuation">) class="token punc tuation">; class="token punc tuation">} class="token func tion">printf class="token punc tuation">( class="token string">"\r\n" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 释放互斥量/二进制信号量 */ class="token func tion">xSemaphoreGive class="token punc tuation">( xLoc kclass="token punc tuation">) class="token punc tuation">; class="token func tion">vTaskDelay class="token punc tuation">( xTic ksToWaitclass="token punc tuation">) class="token punc tuation">; class="token punc tuation">}
class="token punc tuation">} class="token keyword">static class="token keyword">void class="token func tion">vMPTask class="token punc tuation">( class="token keyword">void class="token operator">* pvParameters class="token punc tuation">)
class="token punc tuation">{ class="token keyword">c onst Tic kType_t xTic ksToWait class="token operator">= class="token func tion">pdMS_TO_TICKS class="token punc tuation">( class="token number">30UL class="token punc tuation">) class="token punc tuation">; flagLPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"MPTask start\r\n" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 让LPTask、HPTask先运行 */ class="token func tion">vTaskDelay class="token punc tuation">( xTic ksToWaitclass="token punc tuation">) class="token punc tuation">; class="token c omment">/* 无限循环 */ class="token keyword">for class="token punc tuation">( class="token punc tuation">; class="token punc tuation">; class="token punc tuation">) class="token punc tuation">{ flagLPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; class="token punc tuation">}
class="token punc tuation">} class="token keyword">static class="token keyword">void class="token func tion">vHPTask class="token punc tuation">( class="token keyword">void class="token operator">* pvParameters class="token punc tuation">)
class="token punc tuation">{ class="token keyword">c onst Tic kType_t xTic ksToWait class="token operator">= class="token func tion">pdMS_TO_TICKS class="token punc tuation">( class="token number">10UL class="token punc tuation">) class="token punc tuation">; flagLPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"HPTask start\r\n" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 让LPTask先运行 */ class="token func tion">vTaskDelay class="token punc tuation">( xTic ksToWaitclass="token punc tuation">) class="token punc tuation">; class="token c omment">/* 无限循环 */ class="token keyword">for class="token punc tuation">( class="token punc tuation">; class="token punc tuation">; class="token punc tuation">) class="token punc tuation">{ flagLPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"HPTask wait for Loc k\r\n" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 获得互斥量/二进制信号量 */ class="token func tion">xSemaphoreTake class="token punc tuation">( xLoc kclass="token punc tuation">, portMAX_DELAYclass="token punc tuation">) class="token punc tuation">; flagLPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagMPTaskRun class="token operator">= class="token number">0 class="token punc tuation">; flagHPTaskRun class="token operator">= class="token number">1 class="token punc tuation">; class="token c omment">/* 释放互斥量/二进制信号量 */ class="token func tion">xSemaphoreGive class="token punc tuation">( xLoc kclass="token punc tuation">) class="token punc tuation">; class="token punc tuation">}
class="token punc tuation">} class="token c omment">/*-----------------------------------------------------------*/
c ode>
ckquote> 二进制信号量 实现优先级反转c ;中优先级先于高优先级执行
ckquote>
c="https://img-blog.c sdnimg.c n/direc t/fc 84a435d25540c 58d35ee3fa01edb4c .png" alt="在这里插入图片描述" />
ckquote> 互斥量 实现优先级继承
ckquote>
c="https://img-blog.c sdnimg.c n/direc t/e4a3e59d69d4435a810417298fa385ee.png" alt="在这里插入图片描述" />
三、递归锁
ckquote> 创建递归锁
ckquote>
<c ode c lass="prism language-c pp">class="token c omment">/* 递归锁句柄 */
SemaphoreHandle_t xMutexclass="token punc tuation">; xMutex class="token operator">= class="token func tion">xSemaphoreCreateRec ursiveMutex class="token punc tuation">( class="token punc tuation">) class="token punc tuation">;
c ode>
ckquote> 创建2个任务: 一个上锁, 另一个自己监守自盗(开别人的锁自己用)
ckquote>
<c ode c lass="prism language-c pp"> class="token func tion">xTaskCreate class="token punc tuation">( vTakeTaskclass="token punc tuation">, class="token string">"Task1" class="token punc tuation">, class="token number">1000 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">, class="token number">2 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">) class="token punc tuation">; class="token func tion">xTaskCreate class="token punc tuation">( vGiveAndTakeTaskclass="token punc tuation">, class="token string">"Task2" class="token punc tuation">, class="token number">1000 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">, class="token number">1 class="token punc tuation">, class="token c onstant">NULL class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 启动调度器 */ class="token func tion">vTaskStartSc heduler class="token punc tuation">( class="token punc tuation">) class="token punc tuation">;
c ode>
ckquote> 任务描述
ckquote>
<c ode c lass="prism language-c pp">class="token c omment">/*-----------------------------------------------------------*/
class="token keyword">static class="token keyword">void class="token func tion">vTakeTask class="token punc tuation">( class="token keyword">void class="token operator">* pvParameters class="token punc tuation">)
class="token punc tuation">{ class="token keyword">c onst Tic kType_t xTic ksToWait class="token operator">= class="token func tion">pdMS_TO_TICKS class="token punc tuation">( class="token number">100UL class="token punc tuation">) class="token punc tuation">; BaseType_t xStatusclass="token punc tuation">; class="token keyword">int iclass="token punc tuation">; class="token c omment">/* 无限循环 */ class="token keyword">for class="token punc tuation">( class="token punc tuation">; class="token punc tuation">; class="token punc tuation">) class="token punc tuation">{ class="token c omment">/* 获得递归锁: 上锁 */ xStatus class="token operator">= class="token func tion">xSemaphoreTakeRec ursive class="token punc tuation">( xMutexclass="token punc tuation">, portMAX_DELAYclass="token punc tuation">) class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"Task1 take the Mutex in main loop %s\r\n" class="token punc tuation">, \class="token punc tuation">( xStatus class="token operator">== pdTRUEclass="token punc tuation">) class="token operator">? class="token string">"Suc c ess" class="token operator">: class="token string">"Failed" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 阻塞很长时间, 让另一个任务执行, * 看看它有无办法再次获得递归锁 */ class="token func tion">vTaskDelay class="token punc tuation">( xTic ksToWaitclass="token punc tuation">) class="token punc tuation">; class="token keyword">for class="token punc tuation">( i class="token operator">= class="token number">0 class="token punc tuation">; i class="token operator">< class="token number">10 class="token punc tuation">; iclass="token operator">++ class="token punc tuation">) class="token punc tuation">{ class="token c omment">/* 获得递归锁: 上锁 */ xStatus class="token operator">= class="token func tion">xSemaphoreTakeRec ursive class="token punc tuation">( xMutexclass="token punc tuation">, portMAX_DELAYclass="token punc tuation">) class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"Task1 take the Mutex in sub loop %s, for time %d\r\n" class="token punc tuation">, \class="token punc tuation">( xStatus class="token operator">== pdTRUEclass="token punc tuation">) class="token operator">? class="token string">"Suc c ess" class="token operator">: class="token string">"Failed" class="token punc tuation">, iclass="token punc tuation">) class="token punc tuation">; class="token c omment">/* 释放递归锁 */ class="token func tion">xSemaphoreGiveRec ursive class="token punc tuation">( xMutexclass="token punc tuation">) class="token punc tuation">; class="token punc tuation">} class="token c omment">/* 释放递归锁 */ class="token func tion">xSemaphoreGiveRec ursive class="token punc tuation">( xMutexclass="token punc tuation">) class="token punc tuation">; class="token punc tuation">}
class="token punc tuation">} class="token keyword">static class="token keyword">void class="token func tion">vGiveAndTakeTask class="token punc tuation">( class="token keyword">void class="token operator">* pvParameters class="token punc tuation">)
class="token punc tuation">{ class="token keyword">c onst Tic kType_t xTic ksToWait class="token operator">= class="token func tion">pdMS_TO_TICKS class="token punc tuation">( class="token number">10UL class="token punc tuation">) class="token punc tuation">; BaseType_t xStatusclass="token punc tuation">; class="token c omment">/* 尝试获得递归锁: 上锁 */ xStatus class="token operator">= class="token func tion">xSemaphoreTakeRec ursive class="token punc tuation">( xMutexclass="token punc tuation">, class="token number">0 class="token punc tuation">) class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"Task2: at first, take the Mutex %s\r\n" class="token punc tuation">, \class="token punc tuation">( xStatus class="token operator">== pdTRUEclass="token punc tuation">) class="token operator">? class="token string">"Suc c ess" class="token operator">: class="token string">"Failed" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 如果失败则监守自盗: 开锁 */ class="token keyword">if class="token punc tuation">( xStatus class="token operator">!= pdTRUEclass="token punc tuation">) class="token punc tuation">{ class="token c omment">/* 无法释放别人持有的锁 */ xStatus class="token operator">= class="token func tion">xSemaphoreGiveRec ursive class="token punc tuation">( xMutexclass="token punc tuation">) class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"Task2: give Mutex %s\r\n" class="token punc tuation">, \class="token punc tuation">( xStatus class="token operator">== pdTRUEclass="token punc tuation">) class="token operator">? class="token string">"Suc c ess" class="token operator">: class="token string">"Failed" class="token punc tuation">) class="token punc tuation">; class="token punc tuation">} class="token c omment">/* 如果无法获得, 一直等待 */ xStatus class="token operator">= class="token func tion">xSemaphoreTakeRec ursive class="token punc tuation">( xMutexclass="token punc tuation">, portMAX_DELAYclass="token punc tuation">) class="token punc tuation">; class="token func tion">printf class="token punc tuation">( class="token string">"Task2: and then, take the Mutex %s\r\n" class="token punc tuation">, \class="token punc tuation">( xStatus class="token operator">== pdTRUEclass="token punc tuation">) class="token operator">? class="token string">"Suc c ess" class="token operator">: class="token string">"Failed" class="token punc tuation">) class="token punc tuation">; class="token c omment">/* 无限循环 */ class="token keyword">for class="token punc tuation">( class="token punc tuation">; class="token punc tuation">; class="token punc tuation">) class="token punc tuation">{ class="token c omment">/* 什么都不做 */ class="token func tion">vTaskDelay class="token punc tuation">( xTic ksToWaitclass="token punc tuation">) class="token punc tuation">; class="token punc tuation">}
class="token punc tuation">}
class="token c omment">/*-----------------------------------------------------------*/ c ode>
ckquote> 结果
ckquote>
c="https://img-blog.c sdnimg.c n/direc t/6c 8352ac c 2ef4236bea49642f59195b0.png" alt="在这里插入图片描述" />