提交 11a7137f 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

注解trace模块,其用于跟踪内核各模块运行细节

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    鸿蒙研究站 | http://weharmonyos.com (国内)
              | https://weharmony.github.io (国外)
    oschina | https://my.oschina.net/weharmony
    博客园 | https://www.cnblogs.com/weharmony/
    知乎 | https://www.zhihu.com/people/weharmonyos
    csdn | https://blog.csdn.net/kuangyufei
    51cto | https://harmonyos.51cto.com/column/34
    掘金 | https://juejin.cn/user/756888642000808
    公众号 | 鸿蒙研究站 (weharmonyos)
上级 2d206c4d
/*!
* @file los_exc.c
* @brief 异常接管主文件
* @link
* @verbatim
基本概念
异常接管是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,
例如打印异常发生时当前函数的调用栈信息、CPU现场信息、任务的堆栈情况等。
异常接管作为一种调测手段,可以在系统发生异常时给用户提供有用的异常信息,譬如异常类型、
发生异常时的系统状态等,方便用户定位分析问题。
异常接管,在系统发生异常时的处理动作为:显示异常发生时正在运行的任务信息
(包括任务名、任务号、堆栈大小等),以及CPU现场等信息。
运作机制
每个函数都有自己的栈空间,称为栈帧。调用函数时,会创建子函数的栈帧,
同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。
以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。
ARM处理器中的R13被用作SP
堆栈分析
LR寄存器(Link Register),链接寄存器,指向函数的返回地址。
R11:可以用作通用寄存器,在开启特定编译选项时可以用作帧指针寄存器FP,用来实现栈回溯功能。
GNU编译器(gcc)默认将R11作为存储变量的通用寄存器,因而默认情况下无法使用FP的栈回溯功能。
为支持调用栈解析功能,需要在编译参数中添加-fno-omit-frame-pointer选项,提示编译器将R11作为FP使用。
FP寄存器(Frame Point),帧指针寄存器,指向当前函数的父函数的栈帧起始地址。利用该寄存器可以得到父函数的栈帧,
从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。
当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的
栈帧中的LR、FP寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。
异常接管对系统运行期间发生的芯片硬件异常进行处理,不同芯片的异常类型存在差异,具体异常类型可以查看芯片手册。
异常接管一般的定位步骤如下:
打开编译后生成的镜像反汇编(asm)文件。
搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。
根据LR值查找异常函数的父函数。
重复步骤3,得到函数间的调用关系,找到异常原因。
注意事项
要查看调用栈信息,必须添加编译选项宏-fno-omit-frame-pointer支持stack frame,否则编译时FP寄存器是关闭的。
参考
http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/%E7%94%A8%E6%88%B7%E6%80%81%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF%E8%AF%B4%E6%98%8E.html
@endverbatim
* @version
* @author weharmonyos.com
* @date 2021-11-20
*/
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
......@@ -61,52 +111,6 @@
#ifdef LOSCFG_FS_VFS
#include "console.h"
#endif
/**
* @file los_exc.c
* @brief 软定时器主文件
* @details
* @attention @verbatim
基本概念
异常接管是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,
例如打印异常发生时当前函数的调用栈信息、CPU现场信息、任务的堆栈情况等。
异常接管作为一种调测手段,可以在系统发生异常时给用户提供有用的异常信息,譬如异常类型、
发生异常时的系统状态等,方便用户定位分析问题。
异常接管,在系统发生异常时的处理动作为:显示异常发生时正在运行的任务信息
(包括任务名、任务号、堆栈大小等),以及CPU现场等信息。
运作机制
每个函数都有自己的栈空间,称为栈帧。调用函数时,会创建子函数的栈帧,
同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。
以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。
ARM处理器中的R13被用作SP
堆栈分析
LR寄存器(Link Register),链接寄存器,指向函数的返回地址。
R11:可以用作通用寄存器,在开启特定编译选项时可以用作帧指针寄存器FP,用来实现栈回溯功能。
GNU编译器(gcc)默认将R11作为存储变量的通用寄存器,因而默认情况下无法使用FP的栈回溯功能。
为支持调用栈解析功能,需要在编译参数中添加-fno-omit-frame-pointer选项,提示编译器将R11作为FP使用。
FP寄存器(Frame Point),帧指针寄存器,指向当前函数的父函数的栈帧起始地址。利用该寄存器可以得到父函数的栈帧,
从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。
当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的
栈帧中的LR、FP寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。
异常接管对系统运行期间发生的芯片硬件异常进行处理,不同芯片的异常类型存在差异,具体异常类型可以查看芯片手册。
异常接管一般的定位步骤如下:
打开编译后生成的镜像反汇编(asm)文件。
搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。
根据LR值查找异常函数的父函数。
重复步骤3,得到函数间的调用关系,找到异常原因。
注意事项
要查看调用栈信息,必须添加编译选项宏-fno-omit-frame-pointer支持stack frame,否则编译时FP寄存器是关闭的。
参考
http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/%E7%94%A8%E6%88%B7%E6%80%81%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF%E8%AF%B4%E6%98%8E.html
* @endverbatim
*/
#ifdef LOSCFG_BLACKBOX
#include "los_blackbox.h"
......
/*!
* @file los_trace.c
* @brief
* @link kernel-small-debug-trace http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-debug-trace.html @endlink
@verbatim
基本概念
Trace调测旨在帮助开发者获取内核的运行流程,各个模块、任务的执行顺序,从而可以辅助开发者定位一些时序问题
或者了解内核的代码运行过程。
运行机制
内核提供一套Hook框架,将Hook点预埋在各个模块的主要流程中, 在内核启动初期完成Trace功能的初始化,
并注册Trace的处理函数到Hook中。
当系统触发到一个Hook点时,Trace模块会对输入信息进行封装,添加Trace帧头信息,包含事件类型、
运行的cpuid、运行的任务id、运行的相对时间戳等信息;
Trace提供2种工作模式,离线模式和在线模式。
在线模式需要配合IDE使用,实时将trace frame记录发送给IDE,IDE端进行解析并可视化展示。
离线模式会将trace frame记录到预先申请好的循环buffer中。如果循环buffer记录的frame过多则可能出现翻转,
会覆盖之前的记录,故保持记录的信息始终是最新的信息。Trace循环buffer的数据可以通过shell命令导出进行详细分析,
导出信息已按照时间戳信息完成排序。
@endverbatim
* @image html https://gitee.com/weharmonyos/resources/raw/master/80/trace.png
* @version
* @author weharmonyos.com
* @date 2021-11-20
*/
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
......@@ -239,7 +266,7 @@ STATIC UINT32 OsCreateTraceAgentTask(VOID)
return ret;
}
#endif
/// 跟踪模块初始化
STATIC UINT32 OsTraceInit(VOID)
{
UINT32 ret;
......@@ -291,7 +318,7 @@ STATIC UINT32 OsTraceInit(VOID)
LOS_ERREND:
return ret;
}
/// 启动Trace
UINT32 LOS_TraceStart(VOID)
{
UINT32 intSave;
......@@ -320,7 +347,7 @@ START_END:
TRACE_UNLOCK(intSave);
return ret;
}
/// 停止Trace(跟踪)
VOID LOS_TraceStop(VOID)
{
UINT32 intSave;
......@@ -336,12 +363,12 @@ VOID LOS_TraceStop(VOID)
STOP_END:
TRACE_UNLOCK(intSave);
}
/// 设置事件掩码,仅记录某些模块的事件
VOID LOS_TraceEventMaskSet(UINT32 mask)
{
g_traceMask = mask & EVENT_MASK;
}
/// 输出Trace缓冲区数据
VOID LOS_TraceRecordDump(BOOL toClient)
{
if (g_traceState != TRACE_STOPED) {
......@@ -350,12 +377,12 @@ VOID LOS_TraceRecordDump(BOOL toClient)
}
OsTraceRecordDump(toClient);
}
/// 获取Trace缓冲区的首地址
OfflineHead *LOS_TraceRecordGet(VOID)
{
return OsTraceRecordGet();
}
/// 清除Trace缓冲区中的事件
VOID LOS_TraceReset(VOID)
{
if (g_traceState == TRACE_UNINIT) {
......@@ -365,7 +392,7 @@ VOID LOS_TraceReset(VOID)
OsTraceReset();
}
/// 注册过滤特定中断号事件的钩子函数
VOID LOS_TraceHwiFilterHookReg(TRACE_HWI_FILTER_HOOK hook)
{
UINT32 intSave;
......
......@@ -104,13 +104,13 @@ extern "C" {
/**
* @ingroup los_trace
* Trace state.
* Trace state. | 跟踪状态
*/
enum TraceState {
TRACE_UNINIT = 0, /**< trace isn't inited */
TRACE_INITED, /**< trace is inited but not started yet */
TRACE_STARTED, /**< trace is started and system is tracing */
TRACE_STOPED, /**< trace is stopped */
TRACE_UNINIT = 0, /**< trace isn't inited | 未初始化*/
TRACE_INITED, /**< trace is inited but not started yet | 已初始化但未开始*/
TRACE_STARTED, /**< trace is started and system is tracing | 跟踪进行中...*/
TRACE_STOPED, /**< trace is stopped | 跟踪结束*/
};
/**
......@@ -119,16 +119,16 @@ enum TraceState {
* module's trace mask.
*/
typedef enum {
TRACE_SYS_FLAG = 0x10,
TRACE_HWI_FLAG = 0x20,
TRACE_TASK_FLAG = 0x40,
TRACE_SWTMR_FLAG = 0x80,
TRACE_MEM_FLAG = 0x100,
TRACE_QUE_FLAG = 0x200,
TRACE_EVENT_FLAG = 0x400,
TRACE_SEM_FLAG = 0x800,
TRACE_MUX_FLAG = 0x1000,
TRACE_IPC_FLAG = 0x2000,
TRACE_SYS_FLAG = 0x10, ///< 跟踪系统
TRACE_HWI_FLAG = 0x20, ///< 跟踪硬中断
TRACE_TASK_FLAG = 0x40, ///< 跟踪任务/线程
TRACE_SWTMR_FLAG = 0x80, ///< 跟踪软件定时器
TRACE_MEM_FLAG = 0x100, ///< 跟踪内存
TRACE_QUE_FLAG = 0x200, ///< 跟踪队列
TRACE_EVENT_FLAG = 0x400, ///< 跟踪事件
TRACE_SEM_FLAG = 0x800, ///< 跟踪信号量
TRACE_MUX_FLAG = 0x1000, ///< 跟踪互斥量
TRACE_IPC_FLAG = 0x2000, ///< 跟踪IPC
TRACE_MAX_FLAG = 0x80000000,
TRACE_USER_DEFAULT_FLAG = 0xFFFFFFF0,
......@@ -144,7 +144,7 @@ typedef enum {
* trace_module_flag number
*
*/
typedef enum {
typedef enum { //跟进模块的具体事件
/* 0x10~0x1F */
SYS_ERROR = TRACE_SYS_FLAG | 0,
SYS_START = TRACE_SYS_FLAG | 1,
......@@ -228,24 +228,24 @@ typedef enum {
* struct to store the trace config information.
*/
typedef struct {
UINT32 bigLittleEndian; /**< big little endian flag */
UINT32 clockFreq; /**< system clock frequency */
UINT32 version; /**< trace version */
UINT32 bigLittleEndian; /**< big little endian flag | 大小端标记*/
UINT32 clockFreq; /**< system clock frequency | 系统时钟频率*/
UINT32 version; /**< trace version | 跟踪版本*/
} TraceBaseHeaderInfo;
/**
* @ingroup los_trace
* struct to store the event infomation
* struct to store the event infomation | 保存跟踪事件的信息
*/
typedef struct {
UINT32 eventType; /**< event type */
UINT32 curTask; /**< current running task */
UINT32 curPid; /**< current running processID */
UINT64 curTime; /**< current timestamp */
UINTPTR identity; /**< subject of the event description */
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG
UINT32 eventType; /**< event type | 事件类型*/
UINT32 curTask; /**< current running task | 当前任务ID*/
UINT32 curPid; /**< current running processID | 当前进程ID*/
UINT64 curTime; /**< current timestamp | 时间戳*/
UINTPTR identity; /**< subject of the event description | 描述事件*/
#ifdef LOSCFG_TRACE_FRAME_CORE_MSG //跟踪CPU信息
struct CoreStatus {
UINT32 cpuId : 8, /**< cpuid */
UINT32 cpuId : 8, /**< cpuid | CPU 核 ID*/
hwiActive : 4, /**< whether is in hwi response */
taskLockCnt : 4, /**< task lock count */
paramCount : 4, /**< event frame params' number */
......@@ -415,10 +415,15 @@ extern TRACE_EVENT_HOOK g_traceEventHook;
/**
* @ingroup los_trace
* @brief Trace static code stub.
* @brief Trace static code stub. | 标准插桩
*
* @par Description:
* This API is used to instrument trace code stub in source code, to track events.
\n 1. 相比简易插桩,支持动态过滤事件和参数裁剪,但使用上需要用户按规则来扩展。
\n 2. TYPE用于设置具体的事件类型,可以在头文件los_trace.h中的enum LOS_TRACE_TYPE中自定义事件类型。定义方法和规则可以参考其他事件类型。
\n 3. IDENTITY和Params的类型及含义同简易插桩。
* @attention
* None.
*
......@@ -446,10 +451,14 @@ extern TRACE_EVENT_HOOK g_traceEventHook;
/**
* @ingroup los_trace
* @brief Trace static easier user-defined code stub.
* @brief Trace static easier user-defined code stub. | 简易插桩
*
* @par Description:
* This API is used to instrument user-defined trace code stub in source code, to track events simply.
\n 1. 一句话插桩,用户在目标源代码中插入该接口即可。
\n 2. TYPE有效取值范围为[0, 0xF],表示不同的事件类型,不同取值表示的含义由用户自定义。
\n 3. IDENTITY类型UINTPTR,表示事件操作的主体对象。
\n 4. Params类型UINTPTR,表示事件的参数。
* @attention
* None.
*
......@@ -461,7 +470,7 @@ extern TRACE_EVENT_HOOK g_traceEventHook;
* @par Dependency:
* <ul><li>los_trace.h: the header file that contains the API declaration.</li></ul>
*/
#define LOS_TRACE_EASY(TYPE, IDENTITY, ...) \
#define LOS_TRACE_EASY(TYPE, IDENTITY, ...) \
do { \
UINTPTR _inner[] = {0, ##__VA_ARGS__}; \
UINTPTR _n = sizeof(_inner) / sizeof(UINTPTR); \
......
git add -A
git commit -m ' 动态(堆)内存部分注解, 采用 tlsf 算法
git commit -m ' 注解trace模块,其用于跟踪内核各模块运行细节
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
鸿蒙研究站 | http://weharmonyos.com (国内)
| https://weharmony.github.io (国外)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册