基於小熊派Hi3861鴻蒙開發的IoT物聯網學習【四】
阿新 • • 發佈:2021-07-08
一、互斥鎖基本概念:
1、互斥鎖又稱互斥型訊號量,是一種特殊的二值性訊號量【二值型訊號量可以理解為任務與中斷間或者兩個任務間的標誌,該標誌非“滿”即“空”】,用於實現對共享資源的獨佔式處理。
2、任意時刻互斥鎖的狀態只有兩種:開鎖或閉鎖。
3、當有任務持有時,互斥鎖處於閉鎖狀態,這個任務獲得該互斥鎖的所有權。
4、當該任務釋放時,該互斥鎖被開鎖,任務失去該互斥鎖的所有權。
5、當一個任務持有互斥鎖時,其他任務將不能再對該互斥鎖進行開鎖或持有。
6、多工環境下往往存在多個任務競爭同一共享資源的應用場景,互斥鎖可被用於對共享資源的保護從而實現獨佔式訪問。另外,互斥鎖可以解決訊號量存在的優先順序翻轉問題。
簡單的來說:就是同一時刻,同一資源,只能被同一任務共享;
二、LiteOS提供的互斥鎖具有如下特點:
通過優先順序繼承演算法,解決優先順序翻轉問題。
const char * osMutexGetName (osMutexId_t mutex_id) //獲取互斥鎖物件的名稱。
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) //如果它被鎖定,則獲取互斥鎖或超時值。
osStatus_t osMutexRelease (osMutexId_t mutex_id) //釋放由 osMutexAcquire 獲取的互斥鎖。
osThreadId_tosMutexGetOwner (osMutexId_t mutex_id) //獲取擁有互斥鎖物件的執行緒。
osStatus_t osMutexDelete (osMutexId_t mutex_id) //刪除互斥鎖物件。
在Mutex_example函式中,通過函式建立了互斥鎖ID,並建立的三個不同優先順序的任務, 在第一秒,高優先順序和中優先順序執行緒被延遲。因此,低優先順序執行緒可以啟動自己的工作,獲得互斥鎖並在持有它時延遲。 在第一秒之後,高優先順序和中優先順序執行緒就準備好了。因此高優先順序執行緒獲得優先順序並嘗試獲取互斥鎖。 因為互斥鎖已經被低優先順序執行緒所擁有,所以高優先順序執行緒被阻塞,中間優先順序執行緒被執行,並開始執行許多非阻塞的工作, 3S後低優先順序釋放互斥鎖,高優先順序執行緒準備就緒並立即被排程。
三、cmsis_os2的API互斥鎖(Mutex)介面簡介
struct osMutexAttr_t //互斥鎖的屬性結構體
巨集定義:
#define osMutexRecursive 0x00000001U //遞迴互斥鎖
#define osMutexPrioInherit 0x00000002U //優先順序繼承協議
#define osMutexRobust 0x00000008U //強健的互斥鎖
函式:
osMutexId_tosMutexNew (const osMutexAttr_t *attr) //建立並初始化一個互斥鎖物件。
const char * osMutexGetName (osMutexId_t mutex_id) //獲取互斥鎖物件的名稱。
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) //如果它被鎖定,則獲取互斥鎖或超時值。
osStatus_t osMutexRelease (osMutexId_t mutex_id) //釋放由 osMutexAcquire 獲取的互斥鎖。
osThreadId_tosMutexGetOwner (osMutexId_t mutex_id) //獲取擁有互斥鎖物件的執行緒。
osStatus_t osMutexDelete
互斥鎖作用:相互排斥(廣為人知的互斥鎖)在各種作業系統中用於資源管理。
微控制器器件中的許多資源可以重複使用,但一次只能使用一個執行緒(例如通訊通道,記憶體和檔案)。
互斥鎖用於保護對共享資源的訪問。互斥體被建立並在執行緒之間傳遞(它們可以獲取並釋放互斥鎖)
不能從中斷服務程式(ISR)呼叫互斥鎖管理函式,這與可以從 ISR 釋放的二進位制訊號不同。有關 RTX5 配置選項,請參閱互斥鎖配置。
同一個執行緒可以多次使用互斥鎖,而不會自行鎖定。每當擁有的執行緒獲取互斥鎖時,鎖定計數就會增加。互斥鎖必須多次釋放,
直到鎖計數達到零。在達到零時,互斥鎖實際上被釋放並且可以被其他執行緒獲取。
案例程式碼:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
osMutexId_t mutex_id;
void HighPrioThread(void)
{
// wait 1s until start actual work
osDelay(100U);
while (1)
{
// try to acquire mutex
osMutexAcquire(mutex_id, osWaitForever);
printf("HighPrioThread is runing.\r\n");
osDelay(300U);
osMutexRelease(mutex_id);
}
}
void MidPrioThread(void)
{
// wait 1s until start actual work
osDelay(100U);
while (1)
{
printf("MidPrioThread is runing.\r\n");
osDelay(100);
}
}
void LowPrioThread(void)
{
while (1)
{
osMutexAcquire(mutex_id, osWaitForever);
printf("LowPrioThread is runing.\r\n");
// block mutex for 3s
osDelay(300U);
osMutexRelease(mutex_id);
}
}
void Mutex_example(void)
{
osThreadAttr_t attr;
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024 * 4;
attr.name = "HighPrioThread";
attr.priority = 24;
if (osThreadNew((osThreadFunc_t)HighPrioThread, NULL, &attr) == NULL)
{
printf("Falied to create HighPrioThread!\n");
}
attr.name = "MidPrioThread";
attr.priority = 25;
if (osThreadNew((osThreadFunc_t)MidPrioThread, NULL, &attr) == NULL)
{
printf("Falied to create MidPrioThread!\n");
}
attr.name = "LowPrioThread";
attr.priority = 26;
if (osThreadNew((osThreadFunc_t)LowPrioThread, NULL, &attr) == NULL)
{
printf("Falied to create LowPrioThread!\n");
}
mutex_id = osMutexNew(NULL);
if (mutex_id == NULL)
{
printf("Falied to create Mutex!\n");
}
}
APP_FEATURE_INIT(Mutex_example);
**主要程式碼分析**
在Mutex_example函式中,通過函式建立了互斥鎖ID,並建立的三個不同優先順序的任務, 在第一秒,高優先順序和中優先順序執行緒被延遲。因此,低優先順序執行緒可以啟動自己的工作,獲得互斥鎖並在持有它時延遲。 在第一秒之後,高優先順序和中優先順序執行緒就準備好了。因此高優先順序執行緒獲得優先順序並嘗試獲取互斥鎖。 因為互斥鎖已經被低優先順序執行緒所擁有,所以高優先順序執行緒被阻塞,中間優先順序執行緒被執行,並開始執行許多非阻塞的工作, 3S後低優先順序釋放互斥鎖,高優先順序執行緒準備就緒並立即被排程。
心有猛虎,細嗅薔薇