【FreeRTOS】信號量——簡介、常用API函數、注意事項、項目實現

在FreeRTOS中,信號量是一種非常重要的同步機制,用于實現任務間的互斥訪問和同步操作。通過信號量,不同的任務可以安全地共享資源,避免競爭和沖突,從而確保系統的穩定性和可靠性。本篇博客將介紹FreeRTOS中信號量的基本概念、使用方法和實際應用,幫助讀者深入理解信號量的原理和在實際項目中的應用場景。我們將從信號量的創建、獲取和釋放等方面進行詳細講解,并結合實際的示例代碼,幫助讀者更好地掌握FreeRTOS中信號量的使用技巧和注意事項。通過本篇博客的學習,讀者將能夠更加靈活地運用信號量來實現任務間的同步和資源共享,提高系統的可靠性和效率。


文章目錄

    • 1.信號量簡介
      • 1.1 二值信號量
      • 1.2 計數信號量
      • 1.3 互斥信號量
      • 1.4 遞歸信號量
      • 1.5 信號量控制塊
    • 2.常用信號量API函數
      • 2.1 創建信號量函數
        • 2.1.1 創建二值信號量 xSemaphoreCreateBinary()
        • 2.1.2 創建計數信號量 xSemaphoreCreateCounting()
      • 2.2 信號量刪除函數 vSemaphoreDelete()
      • 2.3 信號量釋放函數
        • 2.3.1 xSemaphoreGive()
        • 2.3.2 xSemaphoreGiveFromISR()
      • 2.4 信號量獲取函數
        • 2.4.1 xSemaphoreTake()
        • 2.4.2 xSemaphoreTakeFromISR()
    • 3.例子說明


1.信號量簡介

信號量Semaphore)是一種實現任務間通信的機制,可以實現任務之間同步或臨界資源的互斥訪問,常用于協助一組相互競爭的任務來訪問臨界資源。在多任務系統中,各任務之間需要同步或互斥實現臨界資源的保護,信號量功能可以為用戶提供這方面的支持。

1.1 二值信號量

二值信號量既可以用于臨界資源訪問也可以用于同步功能。

在這里插入圖片描述

只能取兩個值:01。這種信號量通常用于實現互斥訪問,即只有一個進程或線程可以訪問共享資源。當一個進程或線程占用資源時,二值信號量的值為1,其他進程或線程需要等待,直到信號量的值變為0才能訪問資源。

二值信號量通常用于解決臨界區問題,即多個進程或線程需要訪問共享資源時可能會導致數據不一致或競爭條件的問題。通過使用二值信號量,可以有效地控制對共享資源的訪問,避免出現這些問題。

在實際應用中,二值信號量通常與互斥鎖mutex)結合使用,以實現對共享資源的互斥訪問。當一個進程或線程需要訪問共享資源時,首先嘗試對二值信號量進行加操作,如果成功則可以訪問資源,否則需要等待。在訪問完成后,再對二值信號量進行減操作,釋放資源。


1.2 計數信號量

二進制信號量可以被認為是長度為 1 的隊列,而計數信號量則可以被認為長度大于 1的隊列,信號量使用者依然不必關心存儲在隊列中的消息,只需關心隊列是否有消息即可。

在這里插入圖片描述

一種可以取多個值的信號量,它用于控制對一組資源的訪問數量。計數信號量的值可以大于等于0,表示可用的資源數量。當一個進程或線程需要訪問資源時,它會嘗試對計數信號量進行減操作,如果計數信號量的值大于0,則可以訪問資源,同時計數信號量的值會減少;如果計數信號量的值為0,則需要等待,直到有其他進程或線程釋放資源,使計數信號量的值大于0。

計數信號量通常用于實現對一組資源的并發訪問控制,例如限制同時訪問某個資源的進程或線程的數量。這種機制可以有效地控制資源的并發訪問,避免資源被過度占用,提高系統的性能和穩定性。

在實際應用中,計數信號量可以用于實現線程池、連接池等并發控制的場景,以及限制對其他有限資源的并發訪問。通過合理地管理計數信號量的值,可以有效地控制對資源的并發訪問,避免出現競爭條件和數據不一致的問題。


1.3 互斥信號量

互斥信號量其實是特殊的二值信號量,由于其特有的優先級繼承機制從而使它更適用于簡單互鎖,也就是保護臨界資源。

在這里插入圖片描述

只能取兩個值:0和1。它用于實現對共享資源的互斥訪問,即只有一個進程或線程可以訪問共享資源。當一個進程或線程占用資源時,互斥信號量的值為1,其他進程或線程需要等待,直到信號量的值變為0才能訪問資源。

互斥信號量通常與互斥鎖(mutex)等同步機制結合使用,以實現對共享資源的互斥訪問。在訪問共享資源之前,進程或線程會嘗試對互斥信號量進行減操作,如果成功則可以訪問資源,否則需要等待。在訪問完成后,再對互斥信號量進行加操作,釋放資源。

互斥信號量是實現進程同步和互斥的重要工具,它能夠有效地避免競爭條件和數據不一致的問題。在并發編程中,互斥信號量通常用于保護臨界區,即一段代碼在同一時間只能被一個線程執行,以確保數據的一致性和正確性。


1.4 遞歸信號量

允許同一線程多次對信號量進行加操作,而不會導致死鎖。通常情況下,普通的信號量在同一線程內多次對信號量進行加操作可能會導致死鎖,因為信號量的值會被多次減少,但只有一次加操作來釋放資源。

遞歸信號量則允許同一線程多次對信號量進行加操作,每次加操作都會增加信號量的值,從而避免了死鎖的情況。這種機制通常用于需要在遞歸函數中對共享資源進行加鎖的情況,以及其他需要在同一線程內多次對資源進行加鎖的情況。


1.5 信號量控制塊

在這里插入圖片描述
在這里插入圖片描述


2.常用信號量API函數

2.1 創建信號量函數

2.1.1 創建二值信號量 xSemaphoreCreateBinary()
  • 原型:SemaphoreHandle_t xSemaphoreCreateBinary( void );
  • 作用:用于創建一個二值信號量,用于實現對共享資源的互斥訪問。
  • 參數:無參數。
  • 返回值:返回一個 SemaphoreHandle_t 類型的句柄,表示創建的二值信號量。

xSemaphoreCreateBinary() 函數的作用是創建一個二值信號量,二值信號量的初始值為0,用于實現對共享資源的互斥訪問。它返回一個 SemaphoreHandle_t 類型的句柄,可以用于后續對該二值信號量進行操作。


2.1.2 創建計數信號量 xSemaphoreCreateCounting()
  • 原型:SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount );
  • 作用:用于創建一個計數信號量,用于控制對一組資源的并發訪問數量。
  • 參數:
    • uxMaxCount:計數信號量的最大計數值。
    • uxInitialCount:計數信號量的初始計數值。
  • 返回值:返回一個 SemaphoreHandle_t 類型的句柄,表示創建的計數信號量。

xSemaphoreCreateCounting() 函數用于創建一個計數信號量,計數信號量的初始值為 uxInitialCount,最大計數值為 uxMaxCount。計數信號量通常用于限制對一組資源的并發訪問數量,通過合理地管理計數信號量的值,可以有效地控制對資源的并發訪問,避免出現競爭條件和數據不一致的問題。


2.2 信號量刪除函數 vSemaphoreDelete()

  • 原型:void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
  • 作用:用于刪除一個已經創建的信號量。
  • 參數:
    • xSemaphore:要刪除的信號量的句柄。
  • 返回值:無。

vSemaphoreDelete() 函數用于刪除一個已經創建的信號量,通過傳入要刪除的信號量的句柄 xSemaphore 來實現。一旦刪除了信號量,其句柄將不再有效,并且不能再對該信號量進行操作。


2.3 信號量釋放函數

2.3.1 xSemaphoreGive()
  • 原型:BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );
  • 作用:用于釋放一個二值信號量或增加一個計數信號量的計數值。
  • 參數:
    • xSemaphore:要釋放的信號量的句柄。
  • 返回值:如果釋放成功,則返回 pdTRUE,否則返回 pdFALSE。

xSemaphoreGive() 函數用于釋放一個二值信號量或增加一個計數信號量的計數值。對于二值信號量,調用該函數會將信號量的計數值從 0 增加到 1;對于計數信號量,調用該函數會增加信號量的計數值。如果有任務因等待該信號量而被喚醒,則調用 xSemaphoreGive() 會使其中一個等待的任務得以繼續執行。


2.3.2 xSemaphoreGiveFromISR()
  • 原型:BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
  • 作用:用于從中斷服務程序中釋放一個二值信號量或增加一個計數信號量的計數值。
  • 參數:
    • xSemaphore:要釋放的信號量的句柄。
    • pxHigherPriorityTaskWoken:一個指向 BaseType_t 類型的指針,用于指示是否有一個高優先級任務被喚醒。
  • 返回值:如果釋放成功,則返回 pdTRUE,否則返回 pdFALSE。

xSemaphoreGiveFromISR() 函數與 xSemaphoreGive() 函數類似,用于從中斷服務程序中釋放信號量。它可以用于在中斷服務程序中釋放信號量,以喚醒等待該信號量的任務。與 xSemaphoreGive() 不同的是,xSemaphoreGiveFromISR() 可以喚醒一個等待該信號量的高優先級任務,并通過 pxHigherPriorityTaskWoken 參數指示是否有高優先級任務被喚醒。


2.4 信號量獲取函數

2.4.1 xSemaphoreTake()
  • 原型:BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
  • 作用:用于獲取一個二值信號量或減少一個計數信號量的計數值。
  • 參數:
    • xSemaphore:要獲取的信號量的句柄。
    • xTicksToWait:等待獲取信號量的最長時間,以時鐘節拍數(tick)表示。
  • 返回值:如果成功獲取信號量,則返回 pdTRUE,否則返回 pdFALSE。

xSemaphoreTake() 函數用于獲取一個二值信號量或減少一個計數信號量的計數值。如果信號量的計數值大于 0,則獲取成功,計數值減一;如果信號量的計數值為 0,則任務將進入阻塞狀態,直到信號量可用或超時。

xTicksToWait 參數用于指定任務在獲取信號量時的最長等待時間。如果設置為 portMAX_DELAY,任務將一直等待直到信號量可用;如果設置為 0,則任務將立即返回獲取結果而不進行等待;如果設置為其他數值,則任務將等待指定的時鐘節拍數后返回獲取結果。


2.4.2 xSemaphoreTakeFromISR()
  • 原型:BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken );
  • 作用:用于從中斷服務程序中獲取一個二值信號量或減少一個計數信號量的計數值。
  • 參數:
    • xSemaphore:要獲取的信號量的句柄。
    • pxHigherPriorityTaskWoken:一個指向 BaseType_t 類型的指針,用于指示是否有一個高優先級任務被喚醒。
  • 返回值:如果成功獲取信號量,則返回 pdTRUE,否則返回 pdFALSE。

xSemaphoreTakeFromISR() 函數與 xSemaphoreTake() 函數類似,用于從中斷服務程序中獲取信號量。它可以用于在中斷服務程序中獲取信號量,以等待信號量可用或減少信號量的計數值。與 xSemaphoreTake() 不同的是,xSemaphoreTakeFromISR() 可以喚醒一個等待該信號量的高優先級任務,并通過 pxHigherPriorityTaskWoken 參數指示是否有高優先級任務被喚醒。


3.例子說明

當在STM32上使用FreeRTOS時,可以使用信號量來實現任務間的同步和互斥訪問。以下是一個簡單的示例,演示了如何在STM32上使用FreeRTOS中的信號量。

假設我們有兩個任務:Task1 和 Task2,它們需要共享一個資源,我們可以使用信號量來進行同步。Task1 將獲取資源并執行一些操作,然后釋放資源;Task2 將等待資源可用,然后獲取資源并執行操作。

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"// 定義一個全局的信號量句柄
SemaphoreHandle_t xSemaphore;void Task1(void *pvParameters) {while (1) {// 嘗試獲取信號量,等待最長100個時鐘節拍if (xSemaphoreTake(xSemaphore, 100) == pdTRUE) {// 信號量獲取成功,執行任務1的操作// ...// 釋放信號量xSemaphoreGive(xSemaphore);} else {// 等待超時或者獲取失敗的處理// ...}}
}void Task2(void *pvParameters) {while (1) {// 嘗試獲取信號量,等待最長100個時鐘節拍if (xSemaphoreTake(xSemaphore, 100) == pdTRUE) {// 信號量獲取成功,執行任務2的操作// ...// 釋放信號量xSemaphoreGive(xSemaphore);} else {// 等待超時或者獲取失敗的處理// ...}}
}int main(void) {// 創建一個二值信號量xSemaphore = xSemaphoreCreateBinary();// 創建任務 Task1xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);// 創建任務 Task2xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);// 啟動調度器vTaskStartScheduler();while (1) {// 如果調度器啟動失敗,進行錯誤處理// ...}
}

在上面的示例中,我們首先創建了一個二值信號量 xSemaphore,然后在 Task1Task2 中使用 xSemaphoreTake()xSemaphoreGive() 來獲取和釋放信號量。

在每個任務中,我們使用 xSemaphoreTake() 函數來嘗試獲取信號量。如果獲取成功,任務就可以執行相應的操作;如果獲取失敗,任務將等待一段時間(這里是100個時鐘節拍)然后再次嘗試獲取。獲取成功后,任務執行完操作后使用 xSemaphoreGive() 來釋放信號量。

這樣,通過信號量的獲取和釋放,我們可以實現 Task1 和 Task2 之間的資源共享和同步。這樣的設計可以確保兩個任務之間的操作不會相互干擾,從而實現了任務間的同步和互斥訪問。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207350.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207350.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207350.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

常用Nmap腳本

端口掃描類腳本 Nmap是一款非常流行的端口掃描工具,它可以幫助滲透測試工程師識別目標網絡上開放的端口,并提供有關這些端口的詳細信息。Nmap還提供了一系列基于腳本的功能,這些腳本可以擴展Nmap的功能,使其能夠更深入地探測目標網…

使用Huggingface創建大語言模型RLHF訓練流程的完整教程

ChatGPT已經成為家喻戶曉的名字,而大語言模型在ChatGPT刺激下也得到了快速發展,這使得我們可以基于這些技術來改進我們的業務。 但是大語言模型像所有機器/深度學習模型一樣,從數據中學習。因此也會有garbage in garbage out的規則。也就是說…

AUTOSAR CP Int-Watchdog簡介

Int Watchdog 1 簡介2 EB 中配置 TC39X3 Wdg 在代碼中使用1 簡介 內部看門狗驅動[sws_Wdg_00161]要訪問內部看門狗硬件,對應的 Wdg 模塊實例應該直接訪問看門狗服務的硬件。提示:內部看門狗驅動程序是微控制器抽象層的一部分,它允許直接的硬件訪問。注意:內部看門狗的日常服…

第21章總結 網絡通信

21.1 網絡程序設計基礎 網絡程序設計編寫的是與其他計算機進行通信的程序。Java已經將網絡程序所需要的元素封裝成不同的類,用戶只要創建這些類的對象,使用相應的方法,即使不具備有關的網絡知識,也可以編寫出高質量的網絡通信程序…

【評測腳本】機器信息評測(初版)

背景 QA的實際工作過程中,除了業務相關的測試外,也會涉及到一些評測相關的工作,甚至還要做多版本、多維度的評估分析。尤其是現在火熱的大模型,相關的評測內容更是核心中的核心。當然本文的內容只是做一些初級的機器相關的評測信息,更多更廣的評測需要更多時間的積累和總…

JVM的內存結構詳解「重點篇」

一、JVM虛擬機數據區 虛擬機棧 1、 線程私有 2、 每個方法被執行的時候都會創建一個棧幀用于存儲局部變量表,操作棧,動態鏈接,方法出口等信息。每一個方法被調用的過程就對應一個棧幀在虛擬機棧中從入棧到出棧的過程。 3、棧幀: 是用來存儲…

安裝mysql數據庫

1.1下載APT存儲庫(下載鏈接) 1.2安裝APT存儲庫(注意好正確的路徑) 將下載的文件傳輸到linux服務器對應目錄下后執行以下命令: sudo dpkg -i mysql-apt-config_0.8.10-1_all.deb 選擇mysql5.7 然后點擊ok 然后執行 s…

應用架構——集群、分布式、微服務的概念及異同

一、什么是集群? 集群是指將多臺服務器集中在一起, 每臺服務器都實現相同的業務,做相同的事;但是每臺服務器并不是缺 一不可,存在的主要作用是緩解并發能力和單點故障轉移問題。 集群主要具有以下特征: …

JAVA使用POI向doc加入圖片

JAVA使用POI向doc加入圖片 前言 剛來一個需求需要導出一個word文檔,文檔內是系統某個界面的各種數據圖表,以圖片的方式插入后導出。一番查閱資料于是乎著手開始編寫簡化demo,有關參考poi的文檔查閱 Apache POI Word(docx) 入門示例教程 網上大多數是XXX…

el-table-column 添加 class類

正常添加class 發現沒有效果 class"customClass" 發現并沒有添加上去 看了一下官網發現 class-name 可以實現 第一步: :class-name"customClass" 第二步 : customClass: custom-column-class, 然后就發現可以了

Qt簡介、工程文件分離、創建Qt工程、Qt的幫助文檔

QT 簡介 core:核心模塊,非圖形的接口類,為其它模塊提供支持 gui:圖形用戶接口,qt5之前 widgets:圖形界面相關的類模塊 qt5之后的 database:數據庫模塊 network:網絡模塊 QT 特性 開…

IntelliJ IDEA使用Eval Reset

文章目錄 IntelliJ IDEA使用Eval Reset說明具體操作 IntelliJ IDEA使用Eval Reset 說明 操作系統:windows10 版本:2020.1 IntelliJ IDEA安裝可查看:安裝教程 具體操作 添加,輸入網址 https://plugins.zhile.io然后搜索“IDE E…

IntelliJ IDEA安裝

文章目錄 IntelliJ IDEA安裝說明下載執行安裝 IntelliJ IDEA安裝 說明 操作系統:windows10 版本:2020.1 下載 官網地址 執行安裝

奇點云2023數智科技大會來了,“雙12”直播見!

企業數字化進程深入的同時,也在越來越多的新問題中“越陷越深”: 數據暴漲,作業量和分析維度不同以往,即便加了機器,仍然一查就崩; 終于搞定新增渠道數據的OneID融合,又出現幾個渠道要變更&…

自動定量包裝機市場研究: 2023年行業發展潛力分析

中國包裝機械業取得了快速發展,但也出現了一些低水平重復建設現象。據有關資料顯示,與工業發達國家相比,中國食品和包裝機械產品品種缺乏25%-30%,技術水平落后15-25年。我國包裝專用設備制造行業規模以上企業有319家,主…

Vue3實現一個拾色器功能

? <template><div class"color"><button v-if"hasEyeDrop" click"nativePick">點擊取色</button><input v-else type"color" input"nativePick" v-model"selectedColor" /><p&…

Markdown從入門到精通

Markdown從入門到精通 文章目錄 Markdown從入門到精通前言一、Markdown是什么二、Markdown優點三、Markdown的基本語法3.1 標題3.2 字體3.3 換行3.4 引用3.5 鏈接3.6 圖片3.7 列表3.8 分割線3.9 刪除線3.10 下劃線3.11 代碼塊3.12 表格3.13 腳注3.14 特殊符號 四、Markdown的高…

php爬蟲規則與robots.txt講解

在進行網頁爬蟲時&#xff0c;有一些規則需要遵守&#xff0c;以避免違反法律&#xff0c;侵犯網站隱私和版權&#xff0c;以及造成不必要的麻煩。以下是一些常見的PHP爬蟲規則&#xff1a; 1. 尊重網站的使用條款&#xff1a;在開始爬取之前&#xff0c;請確保你閱讀并理解了…

2024黑龍江省職業院校技能大賽信息安全管理與評估樣題第二三階段

2024黑龍江省職業院校技能大賽暨國賽選拔賽 "信息安全管理與評估"樣題 *第二階段競賽項目試題* 本文件為信息安全管理與評估項目競賽-第二階段試題&#xff0c;第二階段內容包括&#xff1a;網絡安全事件響應、數字取證調查和應用程序安全。 極安云科專注技能競賽…

mysql 快捷登陸

要將 MySQL 的登錄命令添加到環境變量中并為其創建別名&#xff0c;可以按照以下步驟進行操作&#xff1a; 1. 打開終端并編輯 /etc/profile 文件&#xff08;使用所有用戶的全局設置&#xff09; vim /etc/profile 2. 在文件的末尾添加以下行來設置環境變量和別名 # 將 &q…