基本概念
Trace调测旨在帮助开发者获取内核的运行流程,各个模块、任务的执行顺序,从而可以辅助开发者定位一些时序问题或者了解内核的代码运行过程。
运行机制
内核提供一套Hook框架,将Hook点预埋在各个模块的主要流程中, 在内核启动初期完成Trace功能的初始化,并注册Trace的处理函数到Hook中。
当系统触发到一个Hook点时,Trace模块会对输入信息进行封装,添加Trace帧头信息,包含事件类型、运行的cpuid、运行的任务id、运行的相对时间戳等信息;
Trace提供2种工作模式,离线模式和在线模式。
离线模式会将trace frame记录到预先申请好的循环buffer中。如果循环buffer记录的frame过多则可能出现翻转,会覆盖之前的记录,故保持记录的信息始终是最新的信息。Trace循环buffer的数据可以通过shell命令导出进行详细分析,导出信息已按照时间戳信息完成排序。
在线模式需要配合IDE使用,实时将trace frame记录发送给IDE,IDE端进行解析并可视化展示。
接口说明
内核态
LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以查看 API 参考。
表1 Trace模块接口说明
功能分类 | 接口描述 |
---|---|
启停控制 | LOS_TraceStart:启动Trace |
LOS_TraceStop:停止Trace | |
操作Trace记录的数据 | LOS_TraceRecordDump:输出Trace缓冲区数据 |
LOS_TraceRecordGet:获取Trace缓冲区的首地址 | |
LOS_TraceReset:清除Trace缓冲区中的事件 | |
过滤Trace记录的数据 | LOS_TraceEventMaskSet:设置事件掩码,仅记录某些模块的事件 |
屏蔽某些中断号事件 | LOS_TraceHwiFilterHookReg:注册过滤特定中断号事件的钩子函数 |
插桩函数 | LOS_TRACE_EASY:简易插桩 |
LOS_TRACE:标准插桩 |
- 当用户需要针对自定义事件进行追踪时,可按规则在目标源代码中进行插桩,系统提供如下2种插桩接口:
- LOS_TRACE_EASY(TYPE, IDENTITY, params…) 简易插桩。
- 用户在目标源代码中插入该接口即可。
- TYPE有效取值范围为[0, 0xF],表示不同的事件类型,不同取值表示的含义由用户自定义。
- IDENTITY类型UINTPTR,表示事件操作的主体对象。
- Params类型UINTPTR,表示事件的参数。 示例:
- LOS_TRACE_EASY(TYPE, IDENTITY, params…) 简易插桩。
假设需要新增对文件(fd1、fd2)读写操作的简易插桩,
自定义读操作为type:1, 写操作为type:2,则
在读fd1文件的适当位置插入:
LOS_TRACE_EASY(1, fd1, flag, size);
在读fd2文件的适当位置插入:
LOS_TRACE_EASY(1, fd2, flag, size);
在写fd1文件的适当位置插入:
LOS_TRACE_EASY(2, fd1, flag, size);
在写fd2文件的适当位置插入:
LOS_TRACE_EASY(2, fd2,flag, size);
- LOS_TRACE(TYPE, IDENTITY, params…) 标准插桩。
* 相比简易插桩,支持动态过滤事件和参数裁剪,但使用上需要用户按规则来扩展。
* TYPE用于设置具体的事件类型,可以在头文件los_trace.h中的enum LOS_TRACE_TYPE中自定义事件类型。定义方法和规则可以参考其他事件类型。
* IDENTITY和Params的类型及含义同简易插桩。 示例:
1.在enum LOS_TRACE_MASK中定义事件掩码,即模块级别的事件类型。
定义规范为TRACE_#MOD#_FLAG,#MOD#表示模块名。
例如:
TRACE_FS_FLAG = 0x4000
2.在enum LOS_TRACE_TYPE中定义具体事件类型。
定义规范为#TYPE# = TRACE_#MOD#_FLAG | NUMBER,
例如:
FS_REA