<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      RT-Thread 之互斥量使用

      一、互斥量概述

      互斥量(Mutex)是 RT-Thread 中用于解決線程間共享資源獨占訪問的核心 IPC 機制,核心特性是 “二值狀態” 與 “優先級繼承”:僅允許同一時間一個線程持有互斥量(類似 “獨占鎖”),且當低優先級線程持有互斥量時,若高優先級線程請求該資源,低優先級線程會臨時繼承高優先級,避免 “優先級反轉” 問題。

      典型應用場景

      • 多線程競爭硬件外設(如 LED、UART、SPI 總線),防止并發操作導致的設備異常;

      • 多線程讀寫全局數據(如傳感器采集緩存、配置參數),避免數據錯亂;

      • 實時性要求高的場景(如工業控制中高優先級控制線程與低優先級日志線程共享資源)。

      二、互斥量核心 API 函數

      互斥量的操作圍繞 “創建 / 初始化 / 獲取 / 釋放 / 刪除 / 脫離” 展開,需區分動態創建(依賴內存堆)與靜態初始化(基于全局 / 靜態變量),核心參數與功能如下表所示。

      2.1 互斥量的創建與初始化

      類型 函數原型 關鍵參數說明
      動態創建 rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) - name:互斥量名稱(用于 FinSH 調試,如 “mutex_test”)- flag:等待隊列排序方式(RT_IPC_FLAG_FIFO= 先進先出;RT_IPC_FLAG_PRIO= 按線程優先級)
      靜態初始化 rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) - mutex:全局 / 靜態定義的互斥量對象(如struct rt_mutex mutex_test)- 其他參數同動態創建

      2.2 互斥量的獲取

      獲取互斥量即 “申請共享資源”,若互斥量未被持有則直接占用,若已被持有則線程進入阻塞狀態,直到超時或資源釋放。

      函數 功能描述
      rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout) 帶超時獲取:timeout= 等待時間(單位:tick,RT_WAITING_FOREVER= 永久等待,0= 無等待)
      rt_err_t rt_mutex_trytake(rt_mutex_t mutex) 無等待獲取:若互斥量不可用,直接返回RT_EBUSY,不阻塞線程

      2.3 互斥量的釋放與銷毀

      釋放互斥量即 “歸還共享資源”,僅允許持有互斥量的線程調用;銷毀 / 脫離用于回收互斥量占用的資源。

      操作 函數原型 適用場景
      釋放 rt_err_t rt_mutex_release(rt_mutex_t mutex) 線程使用完資源后,歸還互斥量
      動態刪除 rt_err_t rt_mutex_delete(rt_mutex_t mutex) 銷毀動態創建的互斥量(釋放堆內存)
      靜態脫離 rt_err_t rt_mutex_detach(rt_mutex_t mutex) 脫離靜態初始化的互斥量(不釋放內存)

      三、互斥量使用示例

      3.1 源代碼

      #include "thread_task.h"
      #include "main.h"
      #include <stdio.h>      
      #include "rtthread.h"
      #include <rthw.h>
      
      /******************************************** 線程 1 ******************************************************/
      #define THREAD_1_PRIORITY  		4           /* 線程優先級(值越小優先級越高) */
      #define THREAD_1_STACK_SIZE		512         /* 線程棧空間大小(單位:字節) */
      #define THREAD_1_TIMESLICE		10           /* 線程時間片個數(單位:tick) */
      static struct rt_thread *thread_1_handle;    /* 線程句柄 */
      
      /******************************************** 線程 2 ******************************************************/
      #define THREAD_2_PRIORITY  		5           /* 線程優先級(低于線程1) */
      #define THREAD_2_STACK_SIZE		512         /* 線程棧空間大小 */
      #define THREAD_2_TIMESLICE		10           /* 線程時間片個數 */
      static struct rt_thread *thread_2_handle;    /* 線程句柄 */
      
      struct rt_mutex mutex_test;  /* 靜態互斥量對象(全局定義,提前分配內存) */
      
      /**
       * @brief  LED閃爍函數(固定閃爍6次,即3個完整周期)
       * @param  time:每次翻轉后的延遲時間(單位:tick)
       */
      void LED_toggle(uint16_t time)
      {   
          for(uint8_t i = 0; i < 6; i++)  
          {
              HAL_GPIO_TogglePin(GPIOC, LED1_Pin);
              rt_thread_delay(time);      
          }
      }
      
      /**
       * @brief  線程1入口函數(高優先級,10Hz閃爍LED)
       * @param  param:線程參數(未使用,設為RT_NULL)
       */
      void thread_1_entry(void* param)
      {
          while(1)
          {
              /* 帶100ms超時獲取互斥量:非關鍵任務,超時后放棄,避免阻塞 */
              if (rt_mutex_take(&mutex_test, 100) == RT_EOK)
              {
                  LED_toggle(100);
                  /* 釋放互斥量,歸還資源 */            
                  rt_mutex_release(&mutex_test);
              }
              rt_thread_delay(200); 
          }
      }
      
      /**
       * @brief  線程2入口函數(低優先級,1Hz閃爍LED)
       * @param  param:線程參數(未使用,設為RT_NULL)
       */
      void thread_2_entry(void* param)
      {   
          while(1)
          {
              /* 永久等待獲取互斥量:關鍵任務,必須拿到資源才執行 */
              if (rt_mutex_take(&mutex_test, RT_WAITING_FOREVER) == RT_EOK)
              {
                  LED_toggle(1000); 
                  rt_mutex_release(&mutex_test);  
              }
              rt_thread_delay(300); 
          }
      }
      
      /**
       * @brief  初始化互斥量并創建啟動線程(先初始化互斥量,再啟動線程)
       */
      void ThreadStart(void)
      {
          rt_base_t level = rt_hw_interrupt_disable();  
      
          /* 靜態初始化互斥量 */
          rt_mutex_init(
              &mutex_test,            /* 互斥量對象 */
              "mutex_test",         /* 互斥量名稱(用于finsh調試) */
              RT_IPC_FLAG_FIFO       /* 等待隊列按FIFO排序(也可使用 RT_IPC_FLAG_PRIO) */
          );
      
          /* 動態創建并啟動線程1 */
          thread_1_handle = rt_thread_create(
              "thread_1",				/* 線程名稱 */
              thread_1_entry,			/* 線程入口函數 */
              RT_NULL,				/* 線程參數 */
              THREAD_1_STACK_SIZE,	/* 線程棧大小 */
              THREAD_1_PRIORITY,		/* 線程優先級 */
              THREAD_1_TIMESLICE  	/* 線程時間片 */
          );
          if (thread_1_handle != RT_NULL)
              rt_thread_startup(thread_1_handle);  
      
          /* 動態創建并啟動線程2 */
          thread_2_handle = rt_thread_create(
              "thread_2",				/* 線程名稱 */
              thread_2_entry,			/* 線程入口函數 */
              RT_NULL,				/* 線程參數 */
              THREAD_2_STACK_SIZE,	/* 線程棧大小 */
              THREAD_2_PRIORITY,		/* 線程優先級 */
              THREAD_2_TIMESLICE  	/* 線程時間片 */
          );
          if (thread_2_handle != RT_NULL)
              rt_thread_startup(thread_2_handle);  
      
          rt_hw_interrupt_enable(level);  
      }
      
      

      3.2 代碼執行流程

      3.2.1 初始階段(資源初始化)

      1. 調用ThreadStart時,先關閉中斷,避免互斥量初始化被打斷(原子操作);

      2. 靜態初始化互斥量mutex_test,等待隊列按 FIFO 排序,初始狀態為 “未被持有”;

      3. 動態創建線程 1(優先級 4)和線程 2(優先級 5),創建成功后啟動線程;

      4. 恢復中斷,RT-Thread 調度器開始工作,優先調度高優先級線程。

      3.2.2 競爭階段(高優先級線程優先)

      1. 線程 1 優先級高于線程 2,調度器優先切換線程 1 執行;

      2. 線程 1 調用rt_mutex_take(&mutex_test, 100):互斥量未被持有,獲取成功(標記為 “已持有”),執行LED_toggle(100)(10Hz 閃爍 6 次,耗時 600ms);

      3. 線程 2 進入就緒態,因優先級低,等待線程 1 釋放 CPU。

      3.2.3 優先級繼承階段(避免優先級反轉)

      1. 線程 1 閃爍完成后,調用rt_mutex_release(&mutex_test):互斥量恢復 “未持有”,線程 1 執行rt_thread_delay(200)(主動阻塞,釋放 CPU);

      2. 調度器切換線程 2 執行,線程 2 調用rt_mutex_take(&mutex_test, RT_WAITING_FOREVER):獲取成功,執行LED_toggle(1000)(1Hz 閃爍,耗時 6000ms);

      3. 線程 1 的 200ms 延遲結束,進入就緒態:因優先級高,調度器嘗試切換線程 1 執行,但互斥量已被線程 2 持有;

      4. 優先級繼承生效:內核檢測到 “高優先級線程 1 等待低優先級線程 2 的互斥量”,將線程 2 優先級臨時提升至 4(與線程 1 一致),確保線程 2 不被其他線程搶占,加速資源釋放。

      3.2.4 資源釋放與優先級恢復

      1. 線程 2 完成閃爍后,調用rt_mutex_release(&mutex_test):互斥量釋放,喚醒阻塞的線程 1,內核自動將線程 2 優先級恢復為 5;

      2. 調度器切換線程 1 執行,線程 1 成功獲取互斥量,繼續 10Hz 閃爍;

      3. 線程 2 回到就緒態,等待下一次資源競爭。

      3.3 同步效果

      1. 資源獨占保障:LED 始終按單一頻率閃爍(10Hz 或 1Hz),無頻率混亂(如快速閃與慢速閃穿插),證明互斥量阻止了線程對 LED 的并發操作;

      2. 優先級繼承效果:線程 2 持有資源時,不會被其他線程搶占,6000ms 內可快速釋放資源,避免線程 1 長期阻塞;

      3. 超時機制作用:線程 1 的 100ms 超時獲取,若互斥量因異常無法釋放,線程 1 會放棄請求,避免自身永久阻塞(提升系統魯棒性)。

      四、關鍵設計注意事項

      1. 禁止中斷中使用:互斥量的take/release可能導致線程阻塞,而中斷服務函數(ISR)不允許阻塞,因此絕不能在 ISR 中調用互斥量 API;

      2. 成對調用 take/release:獲取互斥量后必須釋放,避免 “死鎖”(如線程 1 獲取后未釋放就阻塞,其他線程無法獲取);

      3. 避免遞歸獲取:同一線程不能多次調用rt_mutex_take獲取同一互斥量(會導致線程自身阻塞),若需遞歸訪問,需使用 RT-Thread 遞歸互斥量(rt_recursive_mutex);

      4. 初始化時機:靜態初始化的互斥量必須在線程啟動前完成(如示例中先初始化mutex_test,再創建線程),避免線程競爭未初始化的資源;

      5. 動態創建的內存管理:動態創建的互斥量(rt_mutex_create)使用完后,需調用rt_mutex_delete銷毀,釋放堆內存,避免內存泄漏。

      總結

      本文詳細解析了 RT-Thread 互斥量的核心特性、API 函數與實操示例,重點說明了 “優先級繼承” 如何解決優先級反轉問題。通過靜態初始化互斥量、多線程競爭 LED 資源的案例,驗證了互斥量在共享資源獨占訪問中的有效性。實際開發中,需結合場景選擇動態 / 靜態方式,遵循 “成對調用、禁止中斷使用” 等規則,確保系統穩定運行。

      posted @ 2025-10-27 00:25  比特向陽  閱讀(19)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 精品麻豆国产色欲色欲色欲WWW| av亚洲在线一区二区| 亚洲国产美女精品久久久| 欧美xxxx精品另类| 无码熟妇人妻av影音先锋| 久久96国产精品久久久| 激情综合网激情五月激情| 久久精品国产福利一区二区| www内射国产在线观看| 国产高清av首播原创麻豆| 国产一卡2卡3卡4卡网站精品| 22222se男人的天堂| 国产桃色在线成免费视频| 亚洲老熟女一区二区三区| 精品午夜福利在线视在亚洲| 人人爽人人爽人人片av东京热| 精品国产成人一区二区| 少妇人妻真实偷人精品| 亚洲无av码一区二区三区| 蜜桃av亚洲精品一区二区| 国产精品自在线拍国产手青青机版 | 亚洲综合在线一区二区三区| 两个人的视频www免费| 国内精品免费久久久久电影院97| 丝袜人妖av在线一区二区| 中文字幕人妻中出制服诱惑| 国产情侣草莓视频在线| 少妇被粗大的猛烈进出动视频| 日本熟妇浓毛| 色一伊人区二区亚洲最大| 大陆一级毛片免费播放| 国产精品中文字幕在线| 久久一级黄色大片免费观看| 欧美成人黄在线观看| 亚洲v国产v天堂a无码二区| 亚洲欧美日韩在线码| 久久毛片少妇高潮| 午夜福利理论片高清在线| 久久碰国产一区二区三区| 亚洲AV无码不卡在线播放| 激情综合色综合啪啪开心|