1. 程式人生 > 其它 >基於小熊派Hi3861鴻蒙開發的IoT物聯網學習【四】

基於小熊派Hi3861鴻蒙開發的IoT物聯網學習【四】

一、互斥鎖基本概念: 1、互斥鎖又稱互斥型訊號量,是一種特殊的二值性訊號量【二值型訊號量可以理解為任務與中斷間或者兩個任務間的標誌,該標誌非“滿”即“空”】,用於實現對共享資源的獨佔式處理。 2、任意時刻互斥鎖的狀態只有兩種:開鎖或閉鎖 3、當有任務持有時,互斥鎖處於閉鎖狀態,這個任務獲得該互斥鎖的所有權。 4、當該任務釋放時,該互斥鎖被開鎖,任務失去該互斥鎖的所有權。 5、當一個任務持有互斥鎖時,其他任務將不能再對該互斥鎖進行開鎖或持有。 6、多工環境下往往存在多個任務競爭同一共享資源的應用場景,互斥鎖可被用於對共享資源的保護從而實現獨佔式訪問。另外,互斥鎖可以解決訊號量存在的優先順序翻轉問題。
簡單的來說:就是同一時刻,同一資源,只能被同一任務共享; 二、LiteOS提供的互斥鎖具有如下特點: 通過優先順序繼承演算法,解決優先順序翻轉問題。

三、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
(osMutexId_t mutex_id) //刪除互斥鎖物件。

互斥鎖作用:相互排斥(廣為人知的互斥鎖)在各種作業系統中用於資源管理。

微控制器器件中的許多資源可以重複使用,但一次只能使用一個執行緒(例如通訊通道,記憶體和檔案)。

互斥鎖用於保護對共享資源的訪問。互斥體被建立並在執行緒之間傳遞(它們可以獲取並釋放互斥鎖)

不能從中斷服務程式(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後低優先順序釋放互斥鎖,高優先順序執行緒準備就緒並立即被排程。
心有猛虎,細嗅薔薇