摘要:本篇先介绍下支持的异常钩子函数的类型,异常钩子函数的注册、执行等内部操作API接口,并介绍下使用异常钩子函数的操作接口。

本文分享自华为云社区《鸿蒙轻内核M核源码分析系列十七(1) 异常钩子函数类型介绍》,作者:zhushy 。

ExcHook异常钩子模块是OpenHarmony LiteOS-M内核的一个可选组件,提供注册钩子函数LOS_RegExcHook、解除注册钩子函数LOS_UnRegExcHook等操作接口。发生系统时,支持保存异常上下文、任务信息、队列信息、中断寄存器状态、任务切换信息、内存分配等信息。由于异常钩子模块内容较多,我们分为几篇进行分析源码,分别介绍异常钩子函数的类型,如何注册和解除注册钩子函数,如何转储异常信息等。本篇先介绍下支持的异常钩子函数的类型,异常钩子函数的注册、执行等内部操作API接口,并介绍下使用异常钩子函数的操作接口。异常钩子函数的注册、执行,异常钩子类型定义在utils\los_debug.h|.c。

本文中所涉及的源码,以OpenHarmony LiteOS-M内核为例,均可以在开源站点kernel_liteos_m: LiteOS kernel for devices with few resources, such as the MCU | 适用于MCU等各种资源极小设备的LiteOS内核 获取。鸿蒙轻内核异常钩子模块代码主要在components\exchook目录下。

1、异常钩子类型枚举EXC_TYPE

在文件utils\los_debug.h定义异常钩子类型枚举EXC_TYPE。EXC_REBOOT用于标记系统重启时的钩子函数,发生重启时调用注册的重启钩子函数;EXC_ASSERT用于标记断言函数,发生断言时调用注册的断言钩子函数;EXC_STACKOVERFLOW用于标记任务栈溢出钩子函数,发生任务栈溢出时调用注册的任务栈溢出钩子函数;EXC_INTERRUPT用于标记中断异常时的钩子函数,发生中断异常时调用注册的中断异常钩子函数。

typedef enum {EXC_REBOOT,EXC_ASSERT,EXC_STACKOVERFLOW,EXC_INTERRUPT,EXC_TYPE_END
} EXC_TYPE;

2、如何注册和执行异常钩子函数

本节我们先看下如何调用和注册异常钩子函数,异常钩子函数的注册和调用的函数API定义在utils\los_debug.c,代码如下。⑴处定义的函数OsExcHookRegister用于注册异常钩子函数到全局变量g_excHook。它的传入的参数ExcHookFn excHookFn是个异常钩子函数,这个钩子函数是定义在文件components\exchook\los_exchook.c中的STATIC VOID DoExcHook(EXC_TYPE excType)后文会详细分析。另外,从代码上可以看出异常钩子函数只有一个,也只能注册一次。⑵处定义的异常钩子执行函数OsDoExcHook,根据传入的枚举类型EXC_TYPE来判断执行什么类型的异常钩子函数。

可以看出这2个函数都是内部函数,用函数OsExcHookRegister注册的也是全局的异常钩子函数,它实质上对应的其实是个异常钩子函数数组。后文会分析如何通过定义在components\exchook\los_exchook.c的LOS_RegExcHook函数如何分别注册不同类型的异常钩子函数。下文也会详细分析其他对外函数如何调用OsDoExcHook来处理异常。

⑴  VOID OsExcHookRegister(ExcHookFn excHookFn){UINT32 intSave = LOS_IntLock();if (!g_excHook) {g_excHook = excHookFn;}LOS_IntRestore(intSave);}⑵  VOID OsDoExcHook(EXC_TYPE excType){UINT32 intSave = LOS_IntLock();if (g_excHook) {g_excHook(excType);}LOS_IntRestore(intSave);}

3、使用异常钩子函数的操作

我们从上文知道,注册的全局异常钩子函数只有一个,那就是全局异常钩子函数变量g_excHook,它根据不同的异常钩子类型来分别处理。我们看下具体如何异常钩子函数的,关于全局异常钩子函数底层的细节后文会详细分析。

3.1 重启LOS_Reboot

该函数可以在发生系统重启异常时调用,程序僵死在此处等待看门狗watchdog等。⑴处根据参数类型EXC_REBOOT调用对应的重启异常钩子函数。需要在系统初始化时执行LOS_RegExcHook(EXC_REBOOT, (ExcHookFn)YourRebootFunction)注册异常钩子函数,才能执行重启异常钩子函数。YourRebootFunction需要自行定义实现在系统重启异常时执行什么操作。如果没有注册过重启钩子函数则跳过不执行任何操作。

LITE_OS_SEC_TEXT_INIT VOID LOS_Reboot(VOID)
{
⑴  OsDoExcHook(EXC_REBOOT);HalSysExit();
}

3.2 断言LOS_ASSERT

该函数可以用于验证函数的参数合法性,该函数宏定义在文件utils\los_debug.h。可以看出,如果设置的打印级别数值太低,时不支持断言功能的。如⑴处代码所示,该函数宏需要一个参数judge。如果参数为假时会执行⑵处的代码,根据参数类型EXC_ASSERT调用对应的断言异常钩子函数。需要在系统初始化时执行LOS_RegExcHook(EXC_ASSERT, (ExcHookFn)YourAssertFunction)注册异常钩子函数,才能执行断言异常钩子函数。YourAssertFunction需要自行定义实现在断言异常时执行什么操作。如果没有注册过断言钩子函数则跳过不执行任何操作。LOS_ASSERT后续的⑶处的代码会关闭中断,打印断言错误信息ASSERT ERROR...。

#if PRINT_LEVEL < LOG_ERR_LEVEL
#define LOS_ASSERT(judge)
#else
#define LOS_ASSERT(judge)                                                          \do {                                                                           \
⑴      if ((judge) == 0) {                                                        \
⑵          OsDoExcHook(EXC_ASSERT);                                               \
⑶          (VOID)LOS_IntLock();                                                   \PRINT_ERR("ASSERT ERROR! %s, %d, %s\n", __FILE__, __LINE__, __func__); \while (1) { }                                                          \}                                                                          \} while (0)
#endif

3.3 任务栈溢出OsDoExcHook(EXC_STACKOVERFLOW)

任务栈溢出OsDoExcHook(EXC_STACKOVERFLOW)被OsHandleRunTaskStackOverflow函数和OsHandleNewTaskStackOverflow函数调用,这2个函数定义在文件kernel\src\los_task.c,分别在当前运行任务,要调度运行的新任务发生任务栈溢出时调用。当执行到⑴、⑵处的代码时,根据参数类型EXC_STACKOVERFLOW调用对应的异常钩子函数。需要在系统初始化时执行LOS_RegExcHook(EXC_STACKOVERFLOW, (ExcHookFn)YourStackOverflowFunction)注册异常钩子函数,才能执行异常钩子函数。YourStackOverflowFunction需要自行定义实现在任务栈溢出异常时执行什么操作。如果没有注册过钩子函数则跳过不执行任何操作。

LITE_OS_SEC_TEXT STATIC VOID OsHandleRunTaskStackOverflow(VOID)
{PRINT_ERR("CURRENT task ID: %s:%d stack overflow!\n",g_losTask.runTask->taskName, g_losTask.runTask->taskID);
⑴  OsDoExcHook(EXC_STACKOVERFLOW);
}
......
LITE_OS_SEC_TEXT STATIC VOID OsHandleNewTaskStackOverflow(VOID)
{......tmp = g_losTask.runTask;g_losTask.runTask = g_losTask.newTask;
⑵  OsDoExcHook(EXC_STACKOVERFLOW);g_losTask.runTask = tmp;
}

3.4 中断异常HalExcHandleEntry

该函数在发生中断异常时汇编代码中调用执行,用于处于系统异常,该函数宏定义在不同芯片架构实现的文件los_interrupt.c中,如kernel\arch\arm\cortex-m7\gcc\los_interrupt.c。处理系统中断异常时,执行到⑴处代码时,会根据参数类型EXC_INTERRUPT调用对应的异常钩子函数。和上述几个异常类型的钩子函数不一样,中断异常钩子函数不需要用户来注册,内核已经注册了中断异常钩子函数。相应的代码在文件components\exchook\los_exc_info.c中,注册代码语句为(VOID)LOS_RegExcHook(EXC_INTERRUPT, (ExcHookFn)OsExcMsgDump);,当发生系统中断异常时会调用(ExcHookFn)OsExcMsgDump函数,后文会详细分析都包含哪些异常信息。

LITE_OS_SEC_TEXT_INIT VOID HalExcHandleEntry(UINT32 excType, UINT32 faultAddr, UINT32 pid, EXC_CONTEXT_S *excBufAddr)
{......
⑴  OsDoExcHook(EXC_INTERRUPT);OsExcInfoDisplay(&g_excInfo);HalSysExit();
}

小结

本文介绍了异常钩子函数的注册函数OsExcHookRegister和异常钩子函数的调用函数OsDoExcHook,以及介绍了支持的异常钩子函数类型等。

点击关注,第一时间了解华为云新鲜技术~

解读鸿蒙轻内核的监控器:异常钩子函数相关推荐

  1. 万字解读鸿蒙轻内核物理内存模块

    摘要:本文首先了解了物理内存管理的结构体,接着阅读了物理内存如何初始化,然后分析了物理内存的申请.释放和查询等操作接口的源代码. 本文分享自华为云社区<鸿蒙轻内核A核源码分析系列三 物理内存&g ...

  2. 深度解读鸿蒙轻内核CPU占用率

    摘要:CPUP(Central Processing Unit Percentage,CPU占用率)分为系统CPU占用率和任务CPU占用率.用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规 ...

  3. 从结构体、内存池初始化到申请释放,详细解读鸿蒙轻内核的动态内存管理

    摘要:本文带领大家一起剖析了鸿蒙轻内核的动态内存模块的源代码,包含动态内存的结构体.动态内存池初始化.动态内存申请.释放等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列九 动态内存Dyna ...

  4. 鸿蒙轻内核源码分析:异常钩子模块系统中断异常,如何转储异常信息

    摘要:本篇介绍下鸿蒙轻内核中异常钩子模块发生系统中断异常时如何转储异常信息. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十七(3) 异常信息ExcInfo>,作者: zhushy. ...

  5. 鸿蒙轻内核M核的故障管家:Fault异常处理

    摘要:本文先简单介绍下Fault异常类型,向量表及其代码,异常处理C语言程序,然后详细分析下异常处理汇编函数实现代码. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十八 Fault异常处理& ...

  6. MPU:鸿蒙轻内核的任务栈的溢出检察官

    摘要:MPU(Memory Protection Unit,内存保护单元)把内存映射为一系列内存区域,定义这些内存区域的维洲,大小,访问权限和内存熟悉信息. 本文分享自华为云社区<鸿蒙轻内核M核 ...

  7. 鸿蒙轻内核M核源码分析:中断Hwi

    摘要:本文带领大家一起剖析了鸿蒙轻内核的中断模块的源代码,掌握中断相关的概念,中断初始化操作,中断创建.删除,开关中断操作等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列五 中断Hwi&g ...

  8. 双向循环链表:鸿蒙轻内核中数据的“驿站”

    本文分享自华为云社区<鸿蒙轻内核M核源码分析系列二 数据结构-双向循环链表>,原文作者:zhushy . 在学习OpenHarmony鸿蒙轻内核源代码的时候,常常会遇到一些数据结构的使用. ...

  9. 鸿蒙轻内核源码分析:虚拟文件系统 VFS

    本文分享自华为云社区<鸿蒙轻内核M核源码分析系列二一 01 虚拟文件系统VFS>,作者:zhushy . VFS(Virtual File System)是文件系统的虚拟层,它不是一个实际 ...

最新文章

  1. 再探@font-face及webIcon制作
  2. elementUI的table组件实现setCurrentRow的滚动条定位效果
  3. Mac安装Open CC进行繁简转化
  4. 1.1.0-简介-P12-分布式锁的解决方案(二)
  5. 2015.4.7-C#入门基础(一)
  6. 自己动手写操作系统 ----总计
  7. Linux: fd_set用法
  8. 读书笔记之《内向者优势》
  9. 【我奶奶都能看懂系列005】☀️python基础语法——容器,小学生也可以学!
  10. INF443 Amphi 2: Calculs d‘Illumination
  11. python 列表作业
  12. Excel从身份证号提取生日
  13. 3分钟读懂RD与RT
  14. 测试透射晶格分析的软件,透射电镜(TEM)电子衍射在晶体结构分析中的应用三...
  15. Linux离线安装JDK1.8
  16. 联想服务器重装2008,联想RD630服务器安装2008R2系统_服务器维修
  17. 通用互联网应用架构图
  18. Supershell 一款牛叉闪闪的工具
  19. 基于多个openEuler物理机执行mugen测试脚本
  20. ZZULIOJ:1028: I love 闰年!

热门文章

  1. 程序员里面开源_开源对年轻程序员意味着什么
  2. jQuery源码分析 Callbacks
  3. Bootstrap3 滚动监听插件的方法
  4. Bootstrap 标准的分页导航
  5. 万有引力的意思_万有引力和引力有什么不同?四种基本性质力中电磁力最多
  6. java 中的scanner_java 中的Scanner
  7. mysql链接出错_请配置/amysql/config.php文件_MySQL数据库之PHP连接mysql时mysql_connect()函数不可用...
  8. linux挂载逻辑卷,CentOS 创建和挂载新的逻辑卷
  9. 查找目录下固定文件目录以及路径(自然排序)
  10. Element表单验证(2)