OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【内核通信机制】下

devtools/2024/9/25 3:59:54/

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
  • 子系统开发内核
  • 轻量系统内核(LiteOS-M)
  • 轻量系统内核(LiteOS-M)【中断管理】
  • 轻量系统内核(LiteOS-M)【任务管理】
  • 轻量系统内核(LiteOS-M)【内存管理】
  • 轻量系统内核(LiteOS-M)【内核通信机制】
  • 轻量系统内核(LiteOS-M)【时间管理】
  • 轻量系统内核(LiteOS-M)【扩展组件】
  • 轻量系统内核(LiteOS-M)【内存调测】
  • 轻量系统内核(LiteOS-M)【异常调测】
  • 轻量系统内核(LiteOS-M)【Trace调测】
  • 轻量系统内核(LiteOS-M)【LMS调测】
  • 轻量系统内核(LiteOS-M)【SHELL】
  • 小型系统内核(LiteOS-A)【概述】
  • 小型系统内核(LiteOS-A)【内核启动】
  • 小型系统内核(LiteOS-A)【中断及异常处理】
  • 标准系统内核(Linux)【New IP内核协议栈】
  • 标准系统内核(Linux)【内核增强特性 > 任务调度】
  • 持续更新中……

读写锁

基本概念

读写锁与互斥锁类似,可用来同步同一进程中的各个任务,但与互斥锁不同的是,其允许多个读操作并发重入,而写操作互斥。

相对于互斥锁的开锁或闭锁状态,读写锁有三种状态:读模式下的锁,写模式下的锁,无锁。

读写锁的使用规则:

  • 保护区无写模式下的锁,任何任务均可以为其增加读模式下的锁。

  • 保护区处于无锁状态下,才可增加写模式下的锁。

多任务环境下往往存在多个任务访问同一共享资源的应用场景,读模式下的锁以共享状态对保护区访问,而写模式下的锁可被用于对共享资源的保护从而实现独占式访问。

这种共享-独占的方式非常适合多任务中读数据频率远大于写数据频率的应用中,提高应用多任务并发度。

运行机制

相较于互斥锁,读写锁如何实现读模式下的锁及写模式下的锁来控制多任务的读写访问呢?

  • 若A任务首次获取了写模式下的锁,有其他任务来获取或尝试获取读模式下的锁,均无法再上锁。

  • 若A任务获取了读模式下的锁,当有任务来获取或尝试获取读模式下的锁时,读写锁计数均加一。

开发指导

接口说明

表1 读写锁模块接口

功能分类接口描述
读写锁的创建和删除- LOS_RwlockInit:创建读写锁
- LOS_RwlockDestroy:删除指定的读写锁
读模式下的锁的申请- LOS_RwlockRdLock:申请指定的读模式下的锁
- LOS_RwlockTryRdLock:尝试申请指定的读模式下的锁
写模式下的锁的申请- LOS_RwlockWrLock:申请指定的写模式下的锁
- LOS_RwlockTryWrLock:尝试申请指定的写模式下的锁
读写锁的释放LOS_RwlockUnLock:释放指定读写锁
读写锁有效性判断LOS_RwlockIsValid:判断读写锁有效性

开发流程

读写锁典型场景的开发流程:

  1. 创建读写锁LOS_RwlockInit。

  2. 申请读模式下的锁LOS_RwlockRdLock或写模式下的锁LOS_RwlockWrLock。

申请读模式下的锁:

*   若无人持有锁,读任务可获得锁。
*   若有人持有锁,读任务可获得锁,读取顺序按照任务优先级。
*   若有人(非自己)持有写模式下的锁,则当前任务无法获得锁,直到写模式下的锁释放。

申请写模式下的锁:

*   若该锁当前没有任务持有,或者持有该读模式下的锁的任务和申请该锁的任务为同一个任务,则申请成功,可立即获得写模式下的锁。
*   若该锁当前已经存在读模式下的锁,且读取任务优先级较高,则当前任务挂起,直到读模式下的锁释放。

3.申请读模式下的锁和写模式下的锁均有三种:无阻塞模式、永久阻塞模式、定时阻塞模式,区别在于挂起任务的时间。

4.释放读写锁LOS_RwlockUnLock。

  • 如果有任务阻塞于指定读写锁,则唤醒被阻塞任务中优先级高的,该任务进入就绪态,并进行任务调度;

  • 如果没有任务阻塞于指定读写锁,则读写锁释放成功。

  1. 删除读写锁LOS_RwlockDestroy。

说明:

  • 读写锁不能在中断服务程序中使用。

  • LiteOS-A内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得读写锁之后,应该尽快释放该锁。

  • 持有读写锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有读写锁任务的优先级

用户态快速互斥锁

基本概念

Futex(Fast userspace mutex,用户态快速互斥锁)是内核提供的一种系统调用能力,通常作为基础组件与用户态的相关锁逻辑结合组成用户态锁,是一种用户态与内核态共同作用的锁,例如用户态mutex锁、barrier与cond同步锁、读写锁。其用户态部分负责锁逻辑,内核态部分负责锁调度。

当用户态线程请求锁时,先在用户态进行锁状态的判断维护,若此时不产生锁的竞争,则直接在用户态进行上锁返回;反之,则需要进行线程的挂起操作,通过Futex系统调用请求内核介入来挂起线程,并维护阻塞队列。

当用户态线程释放锁时,先在用户态进行锁状态的判断维护,若此时没有其他线程被该锁阻塞,则直接在用户态进行解锁返回;反之,则需要进行阻塞线程的唤醒操作,通过Futex系统调用请求内核介入来唤醒阻塞队列中的线程。

运行机制

当用户态产生锁的竞争或释放需要进行相关线程的调度操作时,会触发Futex系统调用进入内核,此时会将用户态锁的地址传入内核,并在内核的Futex中以锁地址来区分用户态的每一把锁,因为用户态可用虚拟地址空间为1GiB,为了便于查找、管理,内核Futex采用哈希桶来存放用户态传入的锁。

当前哈希桶共有80个,0-63号桶用于存放私有锁(以虚拟地址进行哈希),64-79号桶用于存放共享锁(以物理地址进行哈希),私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。

如下图所示,每个futex哈希桶中存放被futex_list串联起来的哈希值相同的futex node,每个futex node对应一个被挂起的task,node中key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。

图1 Futex设计图

Futex操作

Futex模块接口

Futex模块支持以下三种操作:

功能分类接口名称描述
设置线程等待OsFutexWait向Futex表中插入代表被阻塞的线程的node
唤醒被阻塞线程OsFutexWake唤醒一个被指定锁阻塞的线程
调整锁的地址OsFutexRequeue调整指定锁在Futex表中的位置

说明: Futex系统调用通常与用户态逻辑共同组成用户态锁,故推荐使用用户态POSIX接口的锁。

信号

基本概念

信号(signal)是一种常用的进程间异步通信机制,用软件的方式模拟中断信号,当一个进程需要传递信息给另一个进程时,则会发送一个信号给内核,再由内核将信号传递至指定进程,而指定进程不必进行等待信号的动作。

运行机制

信号的运作流程分为三个部分,如表1:

表1 信号的运作流程及相关接口(用户态接口)

功能分类接口名称描述
注册信号回调函数signal注册信号总入口及注册和去注册某信号的回调函数。
注册信号回调函数sigaction功能同signal,但增加了信号发送相关的配置选项,目前仅支持SIGINFO结构体中的部分参数。
发送信号kill
pthread_kill
raise
alarm
abort
发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。
触发回调由系统调用与中断触发,内核态与用户态切换前会先进入用户态指定函数并处理完相应回调函数,再回到原用户态程序继续运行。

说明: 信号机制为提供给用户态程序进程间通信的能力,故推荐使用上表1列出的用户态POSIX相关接口。

注册回调函数:

void *signal(int sig, void (*func)(int))(int);
  • 31 号信号,该信号用来注册该进程的回调函数处理入口,不可重复注册。

  • 0-30 号信号,该信号段用来注册与去注册回调函数。

注册回调函数:

int sigaction(int, const struct sigaction *__restrict, struct sigaction *__restrict); 

支持信号注册的配置修改和配置获取,目前仅支持SIGINFO的选项,SIGINFO内容见sigtimedwait接口内描述。

发送信号:

  • 进程接收信号存在默认行为,单不支持POSIX标准所给出的STOP及CONTINUE、COREDUMP功能。

  • 进程无法屏蔽SIGSTOP、SIGKILL、SIGCONT信号。

  • 某进程后被杀死后,若其父进程不回收该进程,其转为僵尸进程。

  • 进程接收到某信号后,直到该进程被调度后才会执行信号回调。

  • 进程结束后会发送SIGCHLD信号给父进程,该发送动作无法取消。

  • 无法通过信号唤醒处于DELAY状态的进程。


http://www.ppmy.cn/devtools/116794.html

相关文章

《Effective Debugging:软件和系统调试的66个有效方法》读书笔记-Part2

一篇blog,显得略长,本文对应第5-8章,第1-4章请参考Part 1。 编程技术 代码评审、手工执行代码 要点: 检查代码里有没有常见错误;手工执行代码,以验证其是否正确;通过绘图来解析复杂数据结构…

计算机毕业设计之:基于微信小程序的疫苗预约系统的设计与实现(源码+文档+讲解)

博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…

从 Oracle 集群到单节点环境(详细记录一次数据迁移过程)之二:生产服务器的备份操作

从 Oracle 集群到单节点环境(详细记录一次数据迁移过程)之二:生产服务器的备份操作 目录 从 Oracle 集群到单节点环境(详细记录一次数据迁移过程)之二:生产服务器的备份操作一、创建 pfile 文件二、创建备份…

金仓数据库 KingbaseES参考手册-(8.函数(三))

8.51. BIT_AND 用法: bit_and(expression)功能: 聚集函数,计算所有非空值按位与。如果没有非空值传入,返回空值。 例子: CREATE TABLE tinyint_fun(a tinyint); INSERT INTO tinyint_fun values(55); INSERT INTO tiny…

邮储银行:面向金融行业的移动应用安全风险监测案例

本项目通过在移动应用中植入威胁情报探针并结合网络镜像流量方式,利用应用运行过程中设备、系统、应用、行为四个维度数据,将其与设备的关键因子关联生成唯一的移动设备指纹;对手机银行等应用资产进行资产台账梳理;结合服务端大数据分析平台的各种模型规则分析,实时监测移…

重生之我在Java世界------学单例设计模式

什么是单例设计模式? 单例模式是面向对象编程中最简单却又最常用的设计模式之一。它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的原理、常见实现方法、优缺点,以及在使用过程中可能遇到的陷阱。 单…

CTF 技能树 LOG -GIT泄露 笔记

log 使用虚拟机kali操作 python2 安装 apt-get install python2 进入root用户,下载克隆git hack库 git clone https://github.com/BugScanTeam/GitHack sudo passwd root 修改root 命名密码为root 切换登录 su root 终端进入home/kali/GitHack/ python GitH…

mac 怎么查看CPU核数

在 macOS 系统中,可以通过以下几种方法查看 CPU 核心数: 1. 使用“关于本机”查看 点击左上角的苹果图标()。选择“关于本机”。在弹出的窗口中,系统会显示 Mac 的基本信息,包括 CPU 的类型和核心数。比…