鸿蒙轻内核M核源码分析系列十七(2) 异常钩子函数的注册操作

news2024/12/26 15:36:50

本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例,均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。鸿蒙轻内核异常钩子模块代码主要在components\exchook目录下。异常钩子函数的注册、解注册、异常钩子类型定义在utils\los_debug.h|.c


1、异常钩子函数节点结构体和异常钩子函数节点数组

在文件components\exchook\los_exchook.c定义异常钩子的一些宏、函数节点结构体和一些全局变量函数节点数组。⑴处定义的宏设置当前系统支持的钩子函数的个数。⑵处定义的钩子函数节点结构体,每个节点除了异常钩子函数定义还有一个指向下一个节点的指针。⑶处定义的全局变量数组g_excNodes,注册的每一个异常钩子函数都使用一个节点来维护。⑷处定义异常钩子函数节点指针数组,数组的每个元素指针指向对应类型的异常钩子节点单向链表,而最后一个元素g_excHeads[EXC_TYPE_END]指向空闲的钩子函数节点链表。

    #ifndef LOSCFG_BASE_EXC_HOOK_LIMIT
⑴  #define LOSCFG_BASE_EXC_HOOK_LIMIT  16
    #endif

⑵  struct Node {
        ExcHookFn excHookFn;
        struct Node *next;
    };

⑶  STATIC struct Node g_excNodes[LOSCFG_BASE_EXC_HOOK_LIMIT];
⑷  STATIC struct Node *g_excHeads[EXC_TYPE_END + 1]; /* EXC_TYPE_END is used for the free list. */

2、异常钩子函数的注册操作

文件components\exchook\los_exchook.c中主要定义了异常钩子函数的注册LOS_RegExcHook和解除注册LOS_UnRegExcHook对外接口函数。接下来,我们分析注册操作的源代码。

2.1 注册LOS_RegExcHook

在分析注册钩子函数的函数之前,我们先分析下如何通过调用GetFreeNode()获取钩子函数空闲节点,代码如下。g_excHeads[EXC_TYPE_END]指向钩子函数空闲节点单向链表的第一个节点。⑴处如果为空说明未初始化或者空闲节点使用完毕。⑵处如果第1个空闲节点g_excNodes[0]被使用,说明已经没有空闲节点,返回NULL即可。否则执行⑶初始化空闲节点链表,初始化后g_excHeads[EXC_TYPE_END]执行g_excNodes数组的最后一个元素,然后数组的每个元素执行前一个元素,g_excNodes[0]是最后一个空闲节点,如下图所示。然后执行⑷处把函数DoExcHook注册为全局异常钩子函数g_excHook

如果空闲节点链表不为空,执行⑸获取第一个空闲节点,然后g_excHeads[EXC_TYPE_END]指向下一个空闲节点。

STATIC struct Node *GetFreeNode(VOID)
{
    struct Node *node = NULL;
    int i;
⑴  if (g_excHeads[EXC_TYPE_END] == NULL) {
⑵      if (g_excNodes[0].excHookFn != NULL) {
            /* no free node now */
            return NULL;
        } else {
            /* Initialize the free list */
⑶          for (i = 0; i < LOSCFG_BASE_EXC_HOOK_LIMIT; ++i) {
                g_excNodes[i].next = g_excHeads[EXC_TYPE_END];
                g_excHeads[EXC_TYPE_END] = &g_excNodes[i];
            }
⑷          OsExcHookRegister(DoExcHook);
        }
    }

⑸  node = g_excHeads[EXC_TYPE_END];
    g_excHeads[EXC_TYPE_END] = node->next;
    return node;
}

下面我们接着看注册异常钩子函数的LOS_RegExcHook函数的源代码。⑴处先判断传入参数的合法性,⑵处获取空闲钩子函数节点,如果获取节点为空,则无法注册钩子函数。⑶处设置节点的钩子函数成员变量为传入的钩子函数,然后设置其下一个节点为该异常类型对应的钩子函数链表的第一个节点,然后把最后注册的钩子函数节点设置为第一个节点。因此,同一个异常类型可以注册多个钩子函数,他们维护为单向链表,第一个节点为g_excHeads[excType]。后注册的在链表的靠近链表头部。如下图所示。

UINT32 LOS_RegExcHook(EXC_TYPE excType, ExcHookFn excHookFn)
{
    UINT32 intSave;
    struct Node *node = NULL;
⑴  if (excType >= EXC_TYPE_END || excHookFn == NULL) {
        return LOS_ERRNO_SYS_PTR_NULL;
    }

    intSave = LOS_IntLock();
⑵  node = GetFreeNode();
    if (node == NULL) {
        LOS_IntRestore(intSave);
        return LOS_ERRNO_SYS_HOOK_IS_FULL;
    }

⑶  node->excHookFn = excHookFn;
    node->next = g_excHeads[excType];
    g_excHeads[excType] = node;
    LOS_IntRestore(intSave);
    return LOS_OK;
}

2.2 解除注册LOS_UnRegExcHook

我们再看看解除注册钩子函数的LOS_UnRegExcHook函数的源码,⑴处先判断传入参数的合法性。我们已经知道,同一个类型的异常钩子函数节点使用单向链表维护,我们需要执行
⑵处的循环进行遍历。遍历时,判断是否遍历到了要解除注册的函数,如果遍历到了,⑶成立,执行后续的代码。如果⑷成立,说明遍历到的节点不是第一个,把之前的节点执行当前要解除注册的节点的下一个节点,这样把要解除注册的节点从链表中进行删除。否则说明遍历到的节点为第一个,则执行⑸,把遍历到的下一个节点作为第一个节点,这样把要解除注册的节点从链表中进行删除。⑹处置空解除注册的节点,把该节点释放后作为空闲节点插入到钩子函数空闲节点链表g_excHeads[EXC_TYPE_END]的第一个位置上。

UINT32 LOS_UnRegExcHook(EXC_TYPE excType, ExcHookFn excHookFn)
{
    UINT32 intSave;
    struct Node *node = NULL;
    struct Node *preNode = NULL;
⑴  if (excType >= EXC_TYPE_END || excHookFn == NULL) {
        return LOS_ERRNO_SYS_PTR_NULL;
    }

    intSave = LOS_IntLock();
⑵  for (node = g_excHeads[excType]; node != NULL; node = node->next) {
⑶      if (node->excHookFn == excHookFn) {
⑷          if (preNode) {
                preNode->next = node->next;
            } else {
⑸              g_excHeads[excType] = node->next;
            }
⑹          node->excHookFn = NULL;
            node->next = g_excHeads[EXC_TYPE_END];
            g_excHeads[EXC_TYPE_END] = node;
        }
        preNode = node;
    }
    LOS_IntRestore(intSave);
    return LOS_OK;
}

3、异常钩子函数的执行

从上文中,我们了解到初始化钩子函数空闲链表后,通过语句OsExcHookRegister(DoExcHook)注册了异常钩子函数。现在我们就来分析下该函数的源码。DoExcHook函数会调用DoExcHookInRegOrder函数递归运行钩子函数链表上的所有节点维护的钩子函数。⑴处的代码调用函数DoExcHookInRegOrder,除了传入异常类型,还传入该异常类型对应的钩子函数节点链表的第一个节点。⑵处如果链表节点不为空,则递归调用该节点的下一个节点。⑶处执行异常钩子函数。因此,可以看得出,注册早的钩子函数在链表的尾部最先执行,注册晚的函数在链表的头部,最后执行。

STATIC VOID DoExcHookInRegOrder(EXC_TYPE excType, struct Node *node)
{
    if (node != NULL) {
⑵      DoExcHookInRegOrder(excType, node->next);
⑶      node->excHookFn(excType);
    }
}

STATIC VOID DoExcHook(EXC_TYPE excType)
{
    UINT32 intSave;
    if (excType >= EXC_TYPE_END) {
        return;
    }
    intSave = LOS_IntLock();
⑴  DoExcHookInRegOrder(excType, g_excHeads[excType]);
    LOS_IntRestore(intSave);
}


小结

本文介绍了异常钩子模块的对外注册函数LOS_RegExcHook和解除注册函数LOS_UnRegExcHook,对内部维护的钩子函数节点链表有了更深的理解。

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1798257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring框架全系列】SpringBoot_3种配置文件_yml语法_多环境开发配置_配置文件分类(详细)

文章目录 1.三种配置文件2. yaml语法2.1 yaml语法规则2.2 yaml数组数据2.3 yaml数据读取 3. 多环境开发配置3.1 多环境启动配置3.2 多环境启动命令格式3.3 多环境开发控制 4. 配置文件分类 1.三种配置文件 问题导入 框架常见的配置文件有哪几种形式&#xff1f; 比如&#xf…

Perfectly Clear WorkBench v4 解锁版安装教程 (图像修复增强工具)

前言 Perfectly Clear WorkBench 是一款图像修复工具&#xff0c;可以帮助用户对自己的图片素材进行修复&#xff0c;很多的照片因为拍摄问题&#xff0c;或者设备限制&#xff0c;会导致拍摄效果不好&#xff0c;使用这款软件可以进行一定程度的修复&#xff0c;当拍摄时亮度…

RK3588推理RetinaFace出现问题

RK3588推理RetinaFace出现问题 在RK3588上测试RockChip提供的RetinaFace模型时&#xff0c;出现下面的问题 $ python RetinaFace_pic.py done --> Init runtime environment I RKNN: [02:27:16.501] RKNN Runtime Information: librknnrt version: 1.5.2 (c6b7b351a2023…

图片转pdf在线网站,图片转pdf在线网址,工具软件

在现代办公和学习环境中&#xff0c;图片转PDF的操作已变得日益重要。无论是为了存档、分享还是打印&#xff0c;将图片转换为PDF格式都能带来诸多便利。本文将详细介绍几种常用的图片转PDF方法。 打开 “轻云pdf处理官网” &#xff0c;上传图片。 图片上传完成后&#xff0…

C++STL---stack queue知识汇总

前言 C将stack和queue划归到了Containers中&#xff0c;但严格的说这并不准确&#xff0c;stack和queue实际上已经不再是容器了&#xff0c;而是属于容器适配器&#xff0c;适配器做的功能是转换&#xff0c;即&#xff1a;它不是直接实现的&#xff0c;而是由其他容器封装转换…

SOLIDWORKS认证考试的目的

在当今日益发展的工程设计和制造领域&#xff0c;SOLIDWORKS作为一款功能强大的三维CAD设计软件&#xff0c;已经得到了广泛的认可和应用。为了评估和提升用户在使用SOLIDWORKS软件时的专业技能和能力&#xff0c;SOLIDWORKS公司推出了认证考试项目。本文将深入探讨SOLIDWORKS认…

Docker-compose安装、使用,容器化部署springboot项目

目录 一、docker-compose的安装 1、按官网的方式去安装 2、通过pip进行安装 3、离线安装 二、docker-compose常用命令 三、docker-compose.yml 说明 1.基本结构 四、docker-compose部署SpringBoot项目 1.编写docker-compose.yml文件 2.使用docker-compose启动容器…

eNSP学习——RIP与不连续子网

目录 主要命令 原理概述 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、组建基本的RIPv1网络 3&#xff0e;RIPv1中解决不连续子网问题 4&#xff0e;RIPv2中解决不连续子网问题 需要eNSP各种配置命令的点击链接自取&#xff1a;华为&#xff45;NS…

小程序 UI 风格魅力非凡

小程序 UI 风格魅力非凡

web安全基础学习笔记

这里写目录标题 1.使用hackbar2.php漏洞基本分析 弱类型语言2.2 php漏洞找到隐藏的源代码之 index.php~2.3 php漏洞找到隐藏的源代码之 vim的临时文件 /.index.php.swp3.php漏洞基本分析 数组 3.php漏洞基本分析 extract4.php漏洞基本分析 strpos eregi函数漏洞4.php漏洞基本分…

docker学习--最详细的docker run 各子命令解释与应用

文章目录 docker run应用docker run -it那怎样才能退出容器而不用容器关闭呢 docker run -d-p-P--name docker run 容器运行命令 docker run 常见的子命令及其含义 -i 交互式&#xff0c;和-t一起使用 -t 打开一个终端 -d 后台运行 -p/-P 暴露容器中的服务端口 –name 指定容…

如何备份和恢复华为手机?

智能手机已成为我们日常生活中不可或缺的一部分&#xff0c;它们存储着大量敏感数据。因此&#xff0c;确保数据安全&#xff0c;定期备份至关重要&#xff0c;以防手机意外丢失、损坏或被盗。 如果您拥有华为设备&#xff0c;并且正在寻找如何将华为手机备份到PC的方法&#…

接口签名和postman预处理生成签名

nestjs后端代码 controller Get(md5hmacSHA1b64)postMd5hmacSHA1b64(Req() request: Request, Query() query) {// 获取GET请求参数const queryParamsMap new Map(Object.entries(query));return this.handleMd5hmacSHA1b64(queryParamsMap, request);}Post(md5hmacSHA1b64)U…

【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误:消除 Redis 受保护模式的完美方案

【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误&#xff1a;消除 Redis 受保护模式的完美方案 大家好 我是寸铁&#x1f44a; 总结了一篇【Redis】解决 Redis 运行在 Protected Mode 下的 DENIED 错误&#xff1a;消除 Redis 受保护模式的完美方案✨ 喜欢的小伙伴…

RAG 查询检索模块 - 检索 - Pinecone 混合检索方案

虽然向量检索有助于检索给定查询的语义相关块&#xff0c;但它有时在匹配特定关键字词方面缺乏准确性。 为了解决这个问题&#xff0c;混合检索是一种解决方案。该策略充分利用了矢量搜索和关键字搜索等不同检索技术的优势&#xff0c;并将它们智能地组合在一起。使用这种混合…

Linux驱动开发笔记(四)设备树进阶及GPIO、Pinctrl子系统

文章目录 前言一、设备树的进阶知识1. 追加/修改节点内容2.chosen子节点3. 获取设备树节点信息3.1 of_find_node_by_path( )函数3.2 of_find_node_by_name( )函数3.3 of_find_node_by_type( )函数3.4 of_find_compatible_node( )函数3.5 of_find_matching_node_and_match( )函数…

如何将照片从Android传输到笔记本电脑?

目前全球大部分照片都是由手机拍摄的。唯一的问题是这些照片会占用您的内部存储或 SD 卡上的大量空间。如果您的Android设备存储空间不足&#xff0c;您可能会被迫将照片从Android手机传输到笔记本电脑。您访问此网站只是因为您想了解如何将图片从Android传输到笔记本电脑。 如…

Ubuntu24.04开发环境配置

目录 0. 前言1. 宇宙最强编辑器&#xff08;暂定&#xff09;vscode的安装与配置1.1 下载安装1.2 用户配置和常用插件 2. C/C环境配置3. git配置4. MySQL配置5. Java环境配置 0. 前言 本篇博客主要介绍Ubuntu24.04中的开发环境等配置。 1. 宇宙最强编辑器&#xff08;暂定&am…

在大模型AI的下一个战场,为中小创新企业重构竞争格局

麦肯锡预计到2030年前&#xff0c;AI有望为全球经济贡献25.6万亿美元的价值&#xff0c;其中生成式AI的贡献高达7.6万亿美元。自2023年“百模大战”以来&#xff0c;基础大模型的“战事”已经进入尾声&#xff0c;大模型正在“卷向”产业和行业&#xff0c;越来越多的创新企业正…

【每日刷题】Day58

【每日刷题】Day58 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c;​​​​​​​ 1. 3038. 相同分数的最大操作数目 I - 力扣&#xff08;LeetCode&#xff09; 2. 868. …