鸿蒙OpenHarmony【轻量系统内核通信机制(互斥锁)】子系统开发

embedded/2024/9/24 15:41:16/

互斥

基本概念

互斥又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。

任意时刻互斥的状态只有两种,开或闭。当任务持有互斥时,该互斥处于闭状态,这个任务获得该互斥的所有权。当该任务释放互斥时,该互斥被开,任务失去该互斥的所有权。当一个任务持有互斥时,其他任务将不能再对该互斥进行开或持有。

多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥可被用于对共享资源的保护从而实现独占式访问。另外互斥可以解决信号量存在的优先级翻转问题。

运行机制

多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥怎样来避免这种冲突呢?

用互斥处理非共享资源的同步访问时,如果有任务访问该资源,则互斥为加状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥被持有该的任务释放后,其他任务才能重新访问该公共资源,此时互斥再次上,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。

图1 轻量系统互斥运作示意图 1

接口说明

表1 互斥模块接口

功能分类接口描述
互斥的创建和删除LOS_MuxCreate:创建互斥。 LOS_MuxDelete:删除指定的互斥
互斥的申请和释放LOS_MuxPend:申请指定的互斥。 LOS_MuxPost:释放指定的互斥

开发流程

互斥典型场景的开发流程:

  1. 创建互斥LOS_MuxCreate。

  2. 申请互斥LOS_MuxPend。 申请模式有三种:无阻塞模式、永久阻塞模式、定时阻塞模式。

    • 无阻塞模式:任务需要申请互斥,若该互斥当前没有任务持有,或者持有该互斥的任务和申请该互斥的任务为同一个任务,则申请成功。否则直接返回并继续运行当前任务,不会产生阻塞。
    • 永久阻塞模式:任务需要申请互斥,若该互斥当前没有被占用,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥,阻塞任务才会重新得以执行。
    • 定时阻塞模式:任务需要申请互斥,若该互斥当前没有被占用,则申请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥,或者用户指定时间超时后,阻塞任务才会重新得以执行。
  3. 释放互斥LOS_MuxPost。

    • 如果有任务阻塞于指定互斥,则唤醒被阻塞任务中优先级高的,该任务进入就绪态,并进行任务调度;
    • 如果没有任务阻塞于指定互斥,则互斥释放成功。
  4. 删除互斥LOS_MuxDelete。

说明:

  • 互斥支持嵌套,即申请该互斥的任务与已经持有该互斥的任务为同一个任务时会认为申请成功,按申请次数对应的去释放该即可。
  • 互斥不能在中断服务程序中使用。
  • LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥之后,应该尽快释放互斥
  • 持有互斥的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥任务的优先级。

编程实例

实例描述

本实例实现如下流程。

  1. 任务ExampleMutex创建一个互斥任务调度,创建两个任务ExampleMutexTask1、ExampleMutexTask2。ExampleMutexTask2优先级高于ExampleMutexTask1,解任务调度。
  2. ExampleMutexTask2被调度,以永久阻塞模式申请互斥,并成功获取到该互斥,然后任务休眠100Tick,ExampleMutexTask2挂起,ExampleMutexTask1被唤醒。
  3. ExampleMutexTask1以定时阻塞模式申请互斥,等待时间为10Tick,因互斥仍被ExampleMutexTask2持有,ExampleMutexTask1挂起。10Tick超时时间到达后,ExampleMutexTask1被唤醒,以永久阻塞模式申请互斥,因互斥仍被ExampleMutexTask2持有,ExampleMutexTask1挂起。
  4. 100Tick休眠时间到达后,ExampleMutexTask2被唤醒, 释放互斥,唤醒ExampleMutexTask1。ExampleMutexTask1成功获取到互斥后,释放并删除互斥

示例代码

示例代码如下:

本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数ExampleMutex。

#include "los_mux.h"/* 互斥句柄 */
UINT32 g_testMux;VOID ExampleMutexTask1(VOID)
{UINT32 ret;printf("task1 try to get  mutex, wait 10 ticks.\n");/* 申请互斥 */ret = LOS_MuxPend(g_testMux, 10);if (ret == LOS_OK) {printf("task1 get mutex g_testMux.\n");/* 释放互斥,这个分支正常不应该进来 */LOS_MuxPost(g_testMux);LOS_MuxDelete(g_testMux);return;}if (ret == LOS_ERRNO_MUX_TIMEOUT ) {printf("task1 timeout and try to get mutex, wait forever.\n");/* 申请互斥 */ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER);if (ret == LOS_OK) {printf("task1 wait forever, get mutex g_testMux.\n");/* 释放互斥 */LOS_MuxPost(g_testMux);/* 删除互斥 */LOS_MuxDelete(g_testMux);printf("task1 post and delete mutex g_testMux.\n");return;}}return;
}VOID ExampleMutexTask2(VOID)
{printf("task2 try to get  mutex, wait forever.\n");/* 申请互斥 */(VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER);printf("task2 get mutex g_testMux and suspend 100 ticks.\n");/* 任务休眠100Ticks */LOS_TaskDelay(100);printf("task2 resumed and post the g_testMux\n");/* 释放互斥 */LOS_MuxPost(g_testMux);return;
}UINT32 ExampleMutex(VOID)
{UINT32 ret;TSK_INIT_PARAM_S task1 = { 0 };TSK_INIT_PARAM_S task2 = { 0 };UINT32 taskId01;UINT32 taskId02;/* 创建互斥 */LOS_MuxCreate(&g_testMux);/* 任务调度 */LOS_TaskLock();/* 创建任务1 */task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleMutexTask1;task1.pcName       = "MutexTsk1";task1.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;task1.usTaskPrio   = 5;ret = LOS_TaskCreate(&taskId01, &task1);if (ret != LOS_OK) {printf("task1 create failed.\n");return LOS_NOK;}/* 创建任务2 */task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleMutexTask2;task2.pcName       = "MutexTsk2";task2.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;task2.usTaskPrio   = 4;ret = LOS_TaskCreate(&taskId02, &task2);if (ret != LOS_OK) {printf("task2 create failed.\n");return LOS_NOK;}/* 解任务调度 */LOS_TaskUnlock();return LOS_OK;
}

结果验证

编译运行得到的结果为:

task2 try to get  mutex, wait forever.
task2 get mutex g_testMux and suspend 100 ticks.
task1 try to get  mutex, wait 10 ticks.
task1 timeout and try to get mutex, wait forever.
task2 resumed and post the g_testMux
task1 wait forever, get mutex g_testMux.
task1 post and delete mutex g_testMux.

以上就是本篇文章所带来的鸿蒙开发>鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

2

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!
3


http://www.ppmy.cn/embedded/116149.html

相关文章

Redis——笔记01

一、Redis简介 1.1 NoSQL NoSQL(Not Only SQL),意为“不仅仅是SQL”,是一项全新的数据库概念,泛指非关系型的数据库,随着互联网web2.0网站的兴起,传统的关系数据库再应付web2.0网站,特别是超大规模和高并…

数字世界的新秩序:探索Web3的前景

在过去的几十年中,互联网已经彻底改变了我们的生活方式,推动了信息共享、全球互联以及数字经济的快速发展。然而,当前的互联网架构主要是中心化的,由少数大型科技公司控制数据、服务和基础设施。这种模式虽然高效,但也…

java中的位运算

位运算是对整数的二进制位进行操作的一种运算。在java中long, int, short, char和byte类型都可以使用位运算。 位运算的过程如下:首先将十进制整数转换成二进制表示形式,然后将位运算符应用于每个二进制数位,并计算结果。最后,将…

SpringBoot | Maven快速上手

文章目录 一、Maven1.1 Maven 简介:1.2 Maven 的核心功能:1.2.1 项目构建:1.2.2 依赖管理: 1.3 Maven 仓库:1.3.1 本地仓库:1.3.2 中央仓库:1.3.3 私服: 二、第一个 SpringBoot 程序…

揭开数据能力的神秘面纱

在当今数字化时代,数据已成为企业和组织的重要资产。拥有强大的数据能力,能够帮助企业更好地理解市场、客户和业务,从而做出更明智的决策。然而,数据能力究竟是什么?它包含哪些方面?又如何提升呢&#xff1…

Knife4j 一款基于Swagger的开源文档管理工具

一、简单介绍 1.1 简介 Knife4j 是一款基于Swagger的开源文档管理工具&#xff0c;主要用于生成和管理 API 文档 二、使用步骤&#xff1a; 2.1 添加依赖&#xff1a; <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spr…

react hooks--useReducer

概述 很多人看到useReducer的第一反应应该是redux的某个替代品&#xff0c;其实并不是 ◼ useReducer仅仅是useState的一种替代方案&#xff1a;  在某些场景下&#xff0c;如果state的处理逻辑比较复杂&#xff0c;我们可以通过useReducer来对其进行拆分&#xff1b; 或…

SSL 最长签发时间是多久?

在当今数字化的时代&#xff0c;网络安全变得至关重要。为了确保数据在网络传输中的安全性&#xff0c;SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接层&#xff09;证书被广泛应用。那么&#xff0c;SSL最长签发时间是多久呢&#xff1f; SSL证书是一种数字证书&…