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

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

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

      RT-Thread 之信號量使用

      1. 信號量概述

      信號量(Semaphore)是 RT-Thread 中核心的同步與互斥 IPC 機制,根據初始值可分為兩類,適用場景不同:

      • 二值信號量(初始值 = 1):實現互斥訪問,確保同一時間只有一個線程占用共享資源(如硬件外設、全局變量)。
      • 計數信號量(初始值 > 1):實現資源計數,允許指定數量的線程同時訪問共享資源(如有限的緩沖區(qū)、總線接口)。

      典型應用場景:多個傳感器采集線程競爭 I2C 總線時,用初始值為 1 的二值信號量做互斥鎖,避免總線數據沖突;多線程讀取環(huán)形緩沖區(qū)時,用計數信號量統(tǒng)計可用數據量,實現生產者 - 消費者同步。

      2. 信號量核心 API 函數

      信號量的操作圍繞 “創(chuàng)建 / 初始化 / 獲取 / 釋放 / 刪除 / 脫離” 展開,需注意動態(tài)創(chuàng)建靜態(tài)初始化的區(qū)別(動態(tài)依賴內存堆,靜態(tài)基于已分配的全局 / 靜態(tài)變量)。

      2.1 信號量的創(chuàng)建與初始化

      類型 函數原型 關鍵參數說明
      動態(tài)創(chuàng)建 rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) - name:信號量名稱(用于調試)- value:初始值(1 = 互斥,>1 = 計數)- flag:等待隊列排序方式(RT_IPC_FLAG_FIFO= 先進先出;RT_IPC_FLAG_PRIO= 按線程優(yōu)先級)
      靜態(tài)初始化 rt_err_t rt_sem_init(rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag) - sem:全局 / 靜態(tài)定義的信號量對象(需提前分配內存)- 其他參數同動態(tài)創(chuàng)建

      2.2 信號量的獲取

      獲取信號量即 “申請資源”,若信號量值 > 0 則直接占用(值 - 1),若值 = 0 則線程進入阻塞狀態(tài),直到超時或被喚醒。

      函數 功能描述
      rt_sem_take(rt_sem_t sem, rt_int32_t timeout) 帶超時獲取:timeout= 等待時間(單位:tick,RT_WAITING_FOREVER= 永久等待,0= 無等待)
      rt_sem_trytake(rt_sem_t sem) 無等待獲取:若信號量不可用,直接返回錯誤(RT_EBUSY),不阻塞線程

      2.3 信號量的釋放與銷毀

      釋放信號量即 “歸還資源”,會將信號量值 + 1,并按創(chuàng)建時的flag喚醒等待隊列中的線程;銷毀則釋放信號量占用的資源。

      操作 函數原型 適用場景
      釋放 rt_err_t rt_sem_release(rt_sem_t sem) 線程使用完資源后,歸還信號量
      動態(tài)刪除 rt_err_t rt_sem_delete(rt_sem_t sem) 銷毀動態(tài)創(chuàng)建的信號量(釋放堆內存)
      靜態(tài)脫離 rt_err_t rt_sem_detach(rt_sem_t sem) 脫離靜態(tài)初始化的信號量(不釋放內存)

      3. 信號量使用示例

      3.1 源代碼

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

      3.2 代碼執(zhí)行流程

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

      1. 調用ThreadStart時,先關閉中斷,確保信號量初始化不被打斷;
      2. 靜態(tài)初始化信號量sem_test,初始值 = 1(二值互斥模式),等待隊列按 FIFO 排序;
      3. 動態(tài)創(chuàng)建線程 1(優(yōu)先級 4)和線程 2(優(yōu)先級 5),并啟動線程;
      4. 恢復中斷,線程進入就緒狀態(tài),RT-Thread 調度器開始調度。

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

      1. 線程 1 優(yōu)先級(4)高于線程 2(5),調度器優(yōu)先切換線程 1 執(zhí)行;
      2. 線程 1 調用rt_sem_take,信號量值 1→0,獲取成功,開始執(zhí)行LED_toggle(100)(10Hz 閃爍 6 次,耗時 600ms);
      3. 線程 2 同時調用rt_sem_take,信號量值為 0,進入永久阻塞狀態(tài),等待信號量釋放。

      3.2.3 優(yōu)先級調度階段(高優(yōu)先級線程搶占)

      1. 線程 1 閃爍完成后,調用rt_sem_release釋放信號量,值 0→1,同時喚醒阻塞的線程 2;
      2. 此時線程 1 因優(yōu)先級更高,調度器優(yōu)先將線程 1 切換為就緒狀態(tài),線程 1 再次調用rt_sem_take,優(yōu)先獲取信號量,繼續(xù)執(zhí)行;
      3. 線程 2 被喚醒后,發(fā)現信號量已被線程 1 占用,再次進入阻塞狀態(tài),等待下一次信號量釋放。

      3.2.4 交替執(zhí)行特征(LED 表現)

      1. 線程 1(高優(yōu)先級)獲取信號量的概率更高,LED 頻繁以 10Hz 快速閃爍;
      2. 僅當線程 1 釋放信號量后,進入rt_thread_delay(200)延遲時(線程 1 阻塞),線程 2 才能獲取信號量,執(zhí)行 1Hz 慢速閃爍;
      3. 最終 LED 表現:以 10Hz 快速閃爍為主,偶爾插入 1Hz 慢速閃爍,無閃爍混亂(信號量互斥生效)。

      3.2.5 同步效果

      1. 信號量確保 LED 硬件資源同一時間僅被一個線程控制,避免并發(fā)操作導致的閃爍頻率混亂;
      2. 優(yōu)先級機制保證高優(yōu)先級線程(線程 1)的實時性,滿足快速響應需求;
      3. 線程 1 的 100ms 超時獲取,避免因資源長期被占用導致自身阻塞;線程 2 的永久等待,確保關鍵閃爍任務不丟失。
      posted @ 2025-10-29 07:57  比特向陽  閱讀(30)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品亚洲а∨天堂2021| 成人免费ā片在线观看| 精品视频福利| 久久亚洲精品天天综合网| 亚洲精品漫画一二三区| www内射国产在线观看| 国产成人精品久久性色av| 国产馆在线精品极品粉嫩| 欧美videosdesexo吹潮| 久久无码中文字幕免费影院蜜桃| 男人的天堂av一二三区| 国产成人亚洲综合图区| 日韩不卡在线观看视频不卡| 97久久精品午夜一区二区| 国产SM重味一区二区三区| 美日韩在线视频一区二区三区| 久章草在线毛片视频播放| 九色综合国产一区二区三区| 无码激情亚洲一区| 亚洲日韩精品无码一区二区三区 | 超碰成人人人做人人爽| 美女黄网站人色视频免费国产| 欧美日韩国产亚洲沙发| 蜜臀av一区二区三区精品| 亚洲 欧美 唯美 国产 伦 综合| 亚洲人成网站在线在线观看 | 国产在线观看网址不卡一区 | 国产福利片一区二区三区| 伊人精品久久久大香线蕉| 亚洲av二区三区在线| 狠狠色噜噜狠狠亚洲AV| 中文字幕日韩有码国产| 日韩精品国产二区三区| 亚洲色大成网站WWW久久| 另类 专区 欧美 制服| 国产粉嫩美女一区二区三| 国产av无码专区亚洲aⅴ| 亚洲欧美激情在线一区| 在线高清理伦片a| 国产午夜A理论毛片| 国产99久久精品一区二区|