基于小熊派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_t  osMutexNew (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_t  osMutexGetOwner (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后低优先级释放互斥锁,高优先级线程准备就绪并立即被调度。
 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-07-07 23:22  何双新  阅读(269)  评论(0编辑  收藏  举报