本文档介绍了用于收集、存储和传输 Fuchsia 轨迹记录的二进制格式。您可以使用本文档搜索 Fuchsia 轨迹格式中每个字段的详细信息。
概览
跟踪运行期间,跟踪提供程序会使用本文档中所述的二进制格式将记录写入与跟踪管理器共享的跟踪缓冲区 VMO。
二进制格式旨在尽可能减少在写入轨迹时对跟踪对象的性能的影响。记录也会按顺序写入,这样,如果轨迹终止(正常或异常终止),轨迹管理器仍可以通过读取到最后一个格式正确的记录的所有内容,恢复已存储在轨迹缓冲区中的部分轨迹数据。
跟踪记录生成过程中,跟踪记录管理器会汇总参与跟踪记录收集的所有跟踪记录提供程序的记录,并将这些记录与一些特殊的元数据记录串联在一起,以形成跟踪记录归档。
轨迹文件生成完成后,trace
命令行程序等工具可以读取轨迹归档中的轨迹记录,以直观呈现结果,或将其保存到文件以供日后使用。您还可以使用 Perfetto 界面直观呈现轨迹归档文件。
功能
- 占用空间小
- 轨迹记录很紧凑,会将信息打包到少量位中。
- 对字符串、进程和线程进行池化可进一步压缩轨迹数据。
- 内存对齐
- 轨迹记录会在内存中保持 8 字节对齐,以便将其直接写入内存映射的 VMO。
- 可变大小的记录
- 总记录大小上限为 32 KB。
- 大型对象可能需要拆分为多个记录。
- 可扩展
- 您可以根据需要定义新的记录类型。
- 可以跳过无法识别或格式有误的轨迹记录。
编码基元
Fuchsia 轨迹格式具有以下编码基元:
Atoms
每条记录都构建为一系列原子。
每个原子都以 8 字节对齐方式写入,并且大小也为 8 字节的倍数,以便保持对齐。
原子有两种:
- 字:一个 64 位值,可以进一步细分为位字段。字存储为机器字节序(所有当前支持的架构均采用小端字节序)。
- 数据流:一个字节序列,使用零填充到下一个 8 字节边界。数据流以字节顺序存储。长度为 8 字节的倍数的流不会填充(没有零终止符)。
字段是 64 位字的细分,表示为 [<least significant bit> .. <most significant bit>]
,其中第一个和最后一个位位置包括在内。所有未使用的位均预留以供日后使用,并且必须设置为 0。
除非记录格式另有说明,否则字词和字段会存储无符号整数。
数据流可以存储 UTF-8 字符串或二进制数据,具体取决于记录格式。
记录
轨迹记录是二进制编码的轨迹信息,由一系列原子组成。
所有记录都包含一个包含以下基本信息的标题字词:
- 记录类型:一个 4 位字段,用于标识记录的类型及其包含的信息。请参阅记录类型。
- 记录大小:通常是一个 12 位字段,用于指示记录(包括记录头本身)中的字数(8 字节单位的倍数)。记录的可能最大大小为 4095 个字(32760 字节)。非常简单的记录可能只有 1 个字(8 字节)长。 大型记录使用 32 位大小字段,因此具有更大的最大大小。
记录的长度始终为 8 字节的倍数,并以 8 字节对齐方式存储。
存档
轨迹归档是一系列端到端串联的轨迹记录,用于存储轨迹运行期间轨迹提供程序收集的信息,以及用于标识和分隔每个轨迹提供程序生成的轨迹部分的元数据记录。
跟踪归档文件应按顺序读取,因为跟踪记录中较早出现的记录可能会影响对跟踪记录中较晚出现的记录的解读。影响归档中后续记录的记录示例包括字符串引用和线程引用。
无法保证具有关联时间戳的事件记录会按时间戳顺序排列。某些记录类型(例如流事件)需要按时间戳顺序处理事件,因此处理轨迹数据的程序应在处理前按时间戳对事件进行排序。
轨迹系统提供了用于从轨迹归档中提取信息并将其转换为其他形式以进行可视化的工具。
时间戳
时间戳表示为从硬件计数器派生的 64 位滴答。轨迹初始化记录描述了每秒实时滴答数。
默认情况下,我们假设 1 个计时刻等于 1 纳秒。
字符串引用
字符串会编码为字符串引用,它们是采用以下形式的 16 位值:
- 空字符串:值为零。
- 编入索引的字符串:最高有效位为零。低 15 位表示字符串表中的索引,该索引之前是使用字符串记录分配的。
- 内嵌字符串:最高有效位为 1。低 15 位表示字符串的长度(以字节为单位)。字符串的内容会按记录格式指定的方式显示在记录的其他部分中。
为了使轨迹更紧凑,应使用字符串记录将经常引用的字符串(例如事件类别和名称常量)注册到字符串表,然后按索引引用。
字符串表中最多可以包含 32767 个字符串。如果达到此上限,则可以通过替换现有条目或内嵌编码字符串来编码其他字符串。
字符串内容本身会存储为 UTF-8 流,不带结尾。
字符串的理论最大长度为 32767 字节,但在实践中,由于存储包含该字符串的记录的其余部分所需的空间,此长度会进一步缩短,因此我们将字符串的最大长度上限设为保守的 32000 字节。
线程引用
线程和进程内核对象 ID (koid) 编码为线程引用,它们是采用以下形式的 8 位值:
- 内嵌线程:值为零。线程和进程 koid 会按记录格式指定的形式显示在记录的其他部分中。
- 编入索引的线程:值不为零。此值表示线程表中的索引,该索引之前是使用线程记录分配的。
为了使轨迹更紧凑,应使用线程记录将经常引用的线程注册到线程表,然后按索引引用。
字符串表中最多可以有 255 个线程。如果达到此上限,则可以通过替换现有条目或内嵌编码线程来编码其他线程。
用户空间对象信息
轨迹可以包含有关用户空间对象(可使用指针值引用的任何内容,例如 C++ 或 Dart 对象)的注解,形式为用户空间对象记录。轨迹提供程序通常会在创建对象时生成此类记录。
之后,任何引用同一指针的指针参数都将与引用对象的注解相关联。
这样,您就可以轻松地将人类可读的标签和其他信息与轨迹中稍后出现的对象相关联。
内核对象信息
轨迹可以包含有关内核对象记录形式的内核对象(可使用 Zircon koid 引用的任何内容,例如进程、通道或事件)的注释。轨迹提供程序通常会在创建对象时生成此类记录。
之后,任何引用同一 koid 的内核对象 ID 参数都将与引用的注解相关联。
这样,您就可以轻松地将人类可读的标签和其他信息与轨迹中稍后出现的对象相关联。
具体而言,跟踪系统就是通过这种方式将名称与进程和线程 koid 相关联的。
参数
参数是类型化的键值对。
许多记录类型允许向记录附加多达 15 个实参,以提供开发者提供的其他信息。
参数像普通记录一样带有大小前缀,以便跳过无法识别的参数类型。
如需了解详情,请参阅参数类型。
扩展格式
轨迹格式可通过以下方式扩展:
- 定义新的记录类型。
- 在现有记录类型的预留字段中存储新信息。
- 将新信息附加到现有记录类型(可以通过检查记录的大小和载荷来检测此信息是否存在)。
- 定义新的参数类型。
记录类型
记录类型包括:
- 记录标头
- 大记录标头
- 元数据记录(记录类型 = 0)
- 初始化记录(记录类型 = 1)
- 字符串记录(记录类型 = 2)
- 线程记录(记录类型 = 3)
- 事件记录(记录类型 = 4)
- Blob 记录(记录类型 = 5)
- 用户空间对象记录(记录类型 = 6)
- 内核对象记录(记录类型 = 7)
- 安排记录(记录类型 = 8)
- 日志记录(记录类型 = 9)
- 大型 BLOB 记录(记录类型 = 15,大型类型 = 0)
记录标题
所有记录都包含此标头,用于指定记录的类型和大小,以及 48 位数据(用途因记录类型而异)。
格式
标题字词
[0 .. 3]
:记录类型[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 63]
:因记录类型而异(如果未使用,则必须为零)
大记录标题
支持大于 32KB 的记录。大型记录具有 32 位大小字段,而不是常规的 12 位。
标题字词
[0 .. 3]
:记录类型 (15)[4 .. 35]
:记录大小(包括此字),以 8 字节的倍数表示[36 .. 39]
:大型记录类型[40 .. 63]
:因大型记录类型而异(如果未使用,则必须为零)
元数据记录(记录类型 = 0)
提供与后续跟踪数据相关的元数据。
此记录类型预留给轨迹管理器在生成轨迹归档文件时使用。轨迹提供程序本身不得发出该事件。如果轨迹管理器在轨迹提供程序生成的轨迹中遇到元数据记录,则会将其视为垃圾并跳过。
元数据记录有多个子类型,每种子类型都包含不同的信息。
格式
标题字词
[0 .. 3]
:记录类型 (0)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:元数据类型[20 .. 63]
:因元数据类型而异(如果未使用,则必须为零)
提供商信息元数据(元数据类型 = 1)
此元数据用于标识向轨迹贡献了信息的轨迹提供程序。
在遇到下一个提供商部分元数据或提供商信息元数据之前,后续的所有数据都必须来自同一提供商。
格式
标题字词
[0 .. 3]
:记录类型 (0)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:元数据类型 (1)[20 .. 51]
:提供方 ID(用于在轨迹中标识提供方的令牌)[52 .. 59]
:名称长度(以字节为单位)[60 .. 63]
:保留(必须为 0)
provider name stream
- UTF-8 字符串,使用零填充以对齐到 8 字节
提供商版块元数据(元数据类型 = 2)
此元数据用于对从不同提供程序获取的轨迹部分进行分隔。
在遇到下一个提供商部分元数据或提供商信息元数据之前,系统会假定后续的所有数据均来自同一提供商。
读取由来自不同轨迹提供程序的轨迹累积而成的轨迹时,读取器必须为每个提供程序的轨迹(例如初始化数据、字符串表、线程表、用户空间对象表和内核对象表)单独维护状态,并且每当遇到新的提供程序部分元数据记录时,都切换上下文。
格式
标题字词
[0 .. 3]
:记录类型 (0)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:元数据类型 (2)[20 .. 51]
:提供方 ID(用于在轨迹中标识提供方的令牌)[52 .. 63]
:保留(必须为 0)
提供方事件元数据(元数据类型 = 3)
此元数据会提供提供方要报告的事件的运行通知。
此记录可能会出现在输出的任意位置,并且不会对其前面或后面的内容进行分隔。
格式
标题字词
[0 .. 3]
:记录类型 (0)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:元数据类型 (3)[20 .. 51]
:提供方 ID(用于在轨迹中标识提供方的令牌)[52 .. 55]
:事件 ID[56 .. 63]
:保留(必须为 0)
事件
定义了以下事件。
0
:缓冲区已满,记录可能已被丢弃
轨迹信息元数据(元数据类型 = 4)
此元数据提供有关整个轨迹的信息。此记录与特定提供商无关。
格式
标题字词
[0 .. 3]
:记录类型 (0)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:元数据类型 (4)[20 .. 23]
:轨迹信息类型[24 .. 63]
:因轨迹信息类型而异(如果未使用,则必须为零)
魔数记录(轨迹信息类型 = 0)
此记录可指示二进制数据采用 Fuchsia 轨迹格式。通常,它应显示在轨迹的开头。其中不包含任何其他信息。魔法数字 0x16547846
是字符串“FxT”后跟随机选择的一个字节。
为了允许将轨迹的前 8 个字节一起视为一个魔法数字,而无需关心内部记录结构,此记录类型不可扩展。记录不得包含除标题字词以外的任何字词,并且没有任何预留字段。作为一个八字节数值,整个记录的值为 0x0016547846040010。
请注意,该值以及轨迹中的所有其他字的字节顺序取决于写入轨迹的系统的字节序。对于小端序系统,前八个字节为 10 00 04 46 78 54 16 00。在一个大端序系统上,它将是相反的:00 16 54 78 46 04 00 10。
格式
标题字词
[0 .. 3]
:记录类型 (0)[4 .. 15]
:记录大小(包括此字)为 8 字节的倍数 (1)[16 .. 19]
:元数据类型 (4)[20 .. 23]
:轨迹信息类型 (0)[24 .. 55]
:魔数 0x16547846[56 .. 63]
:零
初始化记录(记录类型 = 1)
提供解读后续记录所需的参数。如果没有此记录,读取器可能会假定 1 个计时刻就是 1 纳秒。
格式
标题字词
[0 .. 3]
:记录类型 (1)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 63]
:保留(必须为 0)
“嘀”字母计数器
[0 .. 63]
:每秒滴答数
字符串记录(记录类型 = 2)
在字符串表中注册字符串,为其分配一个介于 0x0001
到 0x7fff
之间的字符串索引。在解读后续记录时,此注册会替换给定字符串索引的所有先前注册。
系统必须忽略尝试为字符串索引 0x0000
设置值的字符串记录,因为此值已预留用于表示空字符串。
必须容忍包含空字符串的字符串记录,但它们没有用处,因为空字符串可以简单地编码为字符串引用中的零。
格式
标题字词
[0 .. 3]
:记录类型 (2)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 30]
:字符串索引(范围为 0x0001 到 0x7fff)[31]
:始终为零 (0)[32 .. 46]
:字符串长度(以字节为单位,范围为 0x0000 到 0x7fff)[47]
:始终为零 (0)[48 .. 63]
:保留(必须为 0)
字符串值流
- UTF-8 字符串,使用零填充以对齐到 8 字节
线程记录(记录类型 = 3)
在线程表中注册进程 ID 和线程 ID 对,并为其分配一个介于 0x01
和 0xff
之间的线程编号。在解读后续记录时,此注册会替换给定线程索引的所有先前注册。
线程索引 0x00
预留用于表示在线程引用中使用内嵌线程 ID。必须忽略尝试为此值设置值的线程记录。
格式
标题字词
[0 .. 3]
:记录类型 (3)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 23]
:线程编号(绝不为 0x00)[24 .. 63]
:保留(必须为 0)
进程 ID 字词
[0 .. 63]
:进程 koid(内核对象 ID)
thread id word
[0 .. 63]
:线程 koid(内核对象 ID)
事件记录(记录类型 = 4)
描述带时间戳的事件。
此记录包含与事件相关的一些基本信息,包括事件发生的时间和地点,以及事件参数和事件子类型专用数据。
格式
标题字词
[0 .. 3]
:记录类型 (4)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:事件类型[20 .. 23]
:参数数量[24 .. 31]
:线程(线程引用)[32 .. 47]
:类别(字符串引用)[48 .. 63]
:名称(字符串引用)
时间戳字词
[0 .. 63]
:计数次数
进程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:进程 koid(内核对象 ID)
线程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:线程 koid(内核对象 ID)
类别串流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数数据(针对每个参数重复)
- (见下文)
事件类型特定数据
- 可以是以下任意一项:
即时事件(事件类型 = 0)
标记此会话中的某个时间点。这些等效于 Zircon 内核探测。
格式
无需事件类型特定数据。
计数器事件(事件类型 = 1)
将每个参数的示例值记录为与计数器的名称和 ID 关联的时间序列中的数据。这些值可以以堆叠面积图的形式图形化呈现。
格式
计数器字词
[0 .. 63]
:计数器 ID
时长开始事件(事件类型 = 2)
标记特定线程上的操作开始。必须与时长结束事件匹配。可以嵌套。
格式
无需事件类型特定数据。
时长结束事件(事件类型 = 3)
标记特定线程上的操作结束。
格式
无需事件类型特定数据。
时长完成事件(事件类型 = 4)
标记特定线程上操作的开始和结束。
格式
结束时间字词
[0 .. 63]
:结束时间的计数次数
异步开始事件(事件类型 = 5)
标记可能跨线程的操作的开始。必须与使用相同异步关联 ID 的异步结束事件匹配。
格式
async 相关字词
[0 .. 63]
:异步关联 ID
异步即时事件(事件类型 = 6)
标记可能跨线程的操作中的某个时刻。必须出现在异步开始事件和异步结束事件之间,并使用相同的异步关联 ID。
格式
async 相关字词
[0 .. 63]
:异步关联 ID
异步结束事件(事件类型 = 7)
标记可能跨线程的操作的结束。
格式
async 相关字词
[0 .. 63]
:异步关联 ID
流开始事件(事件类型 = 8)
标记操作的开始,这会导致一系列操作,这些操作可能会跨多个线程或抽象层。必须与使用相同流程关联 ID 的流程结束事件相匹配。这可以视为时长事件之间的箭头。
流程的开始与此线程的封闭时长事件相关联;它从封闭的时长事件结束的地方开始。
格式
流关联字词
[0 .. 63]
:流程关联 ID
流程步骤事件(事件类型 = 9)
标记流程中的某个点。
该步骤与此线程的封闭时长事件相关联;流程会在封闭时长事件开始时恢复,然后在封闭时长事件结束时暂停。
格式
流关联字词
[0 .. 63]
:流关联 ID
流程结束事件(事件类型 = 10)
标记流程的结束。
流程结束与此线程的封闭时长事件相关联;流程会从封闭时长事件的开始位置恢复。
格式
流关联字词
[0 .. 63]
:流关联 ID
BLOB 记录(记录类型 = 5)
提供要包含在轨迹中的未解析批量数据。这对于将捕获的轨迹数据嵌入其他格式非常有用。
blob 名称用于唯一标识轨迹中的各个 blob 数据流。通过写入多个具有相同名称的 blob 记录,可以将其他数据块附加到之前创建的 blob 中。
BLOB 类型表示 BLOB 内容的表示法。
格式
标题字词
[0 .. 3]
:记录类型 (5)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 31]
:blob 名称(字符串引用)[32 .. 46]
:Blob 载荷大小(以字节为单位,不包括填充)[47 .. 47]
:保留(必须为 0)[48 .. 55]
:blob 类型[56 .. 63]
:保留(必须为 0)
blob 名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
载荷流(可变大小)
- 二进制数据,使用零填充以对齐到 8 字节
Blob 类型
定义了以下 Blob 类型:
TRACE_BLOB_TYPE_DATA
=0x01
:原始的未分类型数据。使用方应知道如何使用它,可能需要根据上下文。TRACE_BLOB_TYPE_LAST_BRANCH
=0x02
:Intel Performance Monitor 的最后分支记录。 格式由 CPU 性能监控器定义。TRACE_BLOB_TYPE_PERFETTO =
0x03`: 该 blob 包含从 Perfetto 说话组件记录的数据。数据采用 Perfetto 的 Proto 格式编码。
用户空间对象记录(记录类型 = 6)
描述用户空间对象、为其分配标签,并可选择将键值对数据作为参数与其相关联。系统会将有关该对象的信息添加到每个进程的用户空间对象表中。
当轨迹使用方遇到值与进程对象表中条目匹配的指针参数事件时,它可以将参数的指针值与之前的用户空间对象记录进行交叉引用,以查找引用的说明。
格式
标题字词
[0 .. 3]
:记录类型 (6)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 23]
:进程(线程引用)[24 .. 39]
:名称(字符串引用)[40 .. 43]
:参数数量[44 .. 63]
:保留(必须为 0)
指针字
[0 .. 63]
:指针值
进程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:进程 koid(内核对象 ID)
名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数数据(针对每个参数重复)
- (见下文)
内核对象记录(记录类型 = 7)
描述内核对象、为其分配标签,并可选择将键值对数据作为参数与其相关联。系统会将与该对象相关的信息添加到全局内核对象表中。
当轨迹使用方遇到具有 koid 参数的事件,且该参数的值与内核对象表中的条目匹配时,它可以将参数的 koid 值与之前的内核对象记录进行交叉引用,以查找引用的说明。
格式
标题字词
[0 .. 3]
:记录类型 (7)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 23]
:内核对象类型(zircon/syscalls/types.h 中的 ZX_OBJ_TYPE_XXX 常量之一[24 .. 39]
:名称(字符串引用)[40 .. 43]
:参数数量[44 .. 63]
:保留(必须为 0)
内核对象 ID 字词
[0 .. 63]
:koid(内核对象 ID)
名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数数据(针对每个参数重复)
- (见下文)
参数惯例
根据惯例,在针对特定类型的对象写入内核对象记录时,轨迹写入器应包含以下命名实参。这有助于跟踪使用方在内核对象之间建立的相关关系。
"process"
:对于ZX_OBJ_TYPE_THREAD
对象,指定包含线程的进程的 koid
时间安排记录(记录类型 = 8)
描述调度事件,例如线程被唤醒的时间,或从一个线程切换到另一个线程的时间。
格式
+---------(4)--------------+--------(48)--------+--(8)--+-(4)-+
| scheduling record type | <type specific> | size | 8 |
+--------------------------+--------------------+-------+-----+
标题字词
[0 .. 3]
:记录类型 (8)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 59]
:安排记录类型专用数据[60 .. 63]
:调度记录类型
上下文切换记录(调度事件记录类型 = 1)
格式
+-(4)-+----(20)---+--------(4)-------+----(16)---+-------(4)-------+----(8)--+-(4)-+
| 1 | reserved | out thread state | cpu | argument count | size | 8 |
+-----+-----------+------------------+-----------+-----------------+---------+-----+
+---------------------------(64)------------------------------+
| timestamp |
+-------------------------------------------------------------+
+---------------------------(64)------------------------------+
| outgoing thread id |
+-------------------------------------------------------------+
+---------------------------(64)------------------------------+
| incoming thread id |
+-------------------------------------------------------------+
+--------------------------(...)------------------------------+
| argument data |
+-------------------------------------------------------------+
标题字词
[0 .. 3]
:记录类型 (8)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:参数个数[20 .. 35]
:CPU 数量[36 .. 39]
:出站线程状态[40 .. 59]
:预留[60 .. 63]
:调度记录类型 (1)
时间戳字词
[0 .. 63]
:计数次数
传出线程 ID
[0 .. 63]
:线程 koid(内核对象 ID)
传入线程 ID
[0 .. 63]
:线程 koid(内核对象 ID)
参数数据(每个参数的重复)
- (如需了解参数格式,请参阅参数)
参数惯例
根据惯例,轨迹写入器在写入此记录时还可以选择包含以下命名参数,以向轨迹使用方提供更多信息。
"incoming_weight"
:Int32
,用于描述传入线程的相对权重"outgoing_weight"
:Int32
,用于描述出站线程的相对权重
线程唤醒记录(调度事件记录类型 = 2)
格式
+-(4)-+----(24)---+----(16)---+-------(4)-------+----(8)--+-(4)-+
| 2 | reserved | cpu | argument count | size | 8 |
+-----+-----------+-----------+-----------------+---------+-----+
+---------------------------(64)------------------------------+
| timestamp |
+-------------------------------------------------------------+
+---------------------------(64)------------------------------+
| waking thread id |
+-------------------------------------------------------------+
+--------------------------(...)------------------------------+
| argument data |
+-------------------------------------------------------------+
标题字词
[0 .. 3]
:记录类型 (8)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 19]
:参数个数。[20 .. 35]
:CPU 数量。[60 .. 63]
:调度记录类型 (2)
时间戳字词
[0 .. 63]
:计数次数
唤醒线程 ID
[0 .. 63]
:线程 koid(内核对象 ID)
参数数据(每个参数的重复)
- (如需了解参数格式,请参阅参数)
参数惯例
根据惯例,轨迹写入器在写入此记录时还可以选择添加以下命名参数,以向轨迹使用方提供更多信息。
"weight"
:Int32
,用于描述唤醒线程的相对权重
旧版上下文切换记录(上下文切换记录类型 = 0)
随着 Fuchsia 调度机制的不断发展,此记录已不再是一种有效的上下文切换模型。它保留是为了实现向后兼容性。
该记录指定了上下文切换后传出线程的新状态。从定义上讲,由于传入线程刚刚被恢复,因此其新状态为“正在运行”。
格式
[0 .. 3]
:记录类型 (8)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 23]
:CPU 数量[24 .. 27]
:传出线程状态(除“正在运行”之外的以下任意值)[28 .. 35]
:出站线程(线程引用)[36 .. 43]
:传入线程(线程引用)[44 .. 51]
:出站线程优先级[52 .. 59]
:传入线程优先级[60 .. 63]
:调度记录类型 (0)
时间戳字词
[0 .. 63]
:计数次数
出站进程 ID 字词(除非出站线程引用表示内嵌线程,否则省略)
[0 .. 63]
:进程 koid(内核对象 ID)
出站线程 ID 字词(除非出站线程引用表示内嵌线程,否则省略)
[0 .. 63]
:线程 koid(内核对象 ID)
传入进程 ID 字词(除非传入线程引用表示内嵌线程,否则省略)
[0 .. 63]
:进程 koid(内核对象 ID)
传入线程 ID 字词(除非传入线程引用表示内嵌线程,否则省略)
[0 .. 63]
:线程 koid(内核对象 ID)
线程状态
定义了以下线程状态:
0
:新1
:正在运行2
:已暂停3
:已屏蔽4
:正在终止5
:已停用
这些值与 zircon/syscalls/object.h 中的 ZX_THREAD_STATE_XXX
常量一致。
日志记录(记录类型 = 9)
描述在特定时间点写入日志的消息。
格式
标题字词
[0 .. 3]
:记录类型 (9)[4 .. 15]
:记录大小(包括此字),以 8 字节的倍数表示[16 .. 30]
:日志消息长度(以字节为单位,范围为 0x0000 到 0x7fff)[31]
:始终为零 (0)[32 .. 39]
:线程(线程引用)[40 .. 63]
:保留(必须为 0)
时间戳字词
[0 .. 63]
:计数次数
进程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:进程 koid(内核对象 ID)
线程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:线程 koid(内核对象 ID)
日志消息流
- UTF-8 字符串,使用零填充以对齐到 8 字节
大型 BLOB 记录(记录类型 = 15,大型类型 = 0)
提供要嵌入轨迹中的大型二进制 BLOB 数据。它使用大型记录标头。
大型 BLOB 记录支持多种不同的格式。这些格式可用于更改记录中包含的 BLOB 数据和元数据的类型。
格式
标题字词
[0 .. 3]
:记录类型 (15)[4 .. 35]
:记录大小(包括此字),以 8 字节的倍数表示[36 .. 39]
:大型记录类型 (0)[40 .. 43]
:blob 格式类型[44 .. 63]
:保留,必须为 0
带有元数据的带内大型 blob 记录(blob 格式 = 0)
此类型包含记录本身中的 blob 数据和元数据。除了类别和名称之外,元数据还包括时间戳、线程/进程信息和实参。
该名称应足以标识 blob 中包含的数据类型。
格式
标题字词
[0 .. 3]
:记录类型 (15)[4 .. 35]
:记录大小(包括此字),以 8 字节的倍数表示[36 .. 39]
:大型记录类型 (0)[40 .. 43]
:blob 格式类型 (0)[44 .. 63]
:保留,必须为 0
设置标题格式
[0 .. 15]
:类别(字符串引用)[16 .. 31]
:名称(字符串引用)[32 .. 35]
:参数数量[36 .. 43]
:线程(线程引用)[44 .. 63]
:保留,必须为 0
类别串流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
时间戳字词
[0 .. 63]
:计数次数
进程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:进程 koid(内核对象 ID)
线程 ID 字词(除非线程引用表示内嵌线程,否则省略)
[0 .. 63]
:线程 koid(内核对象 ID)
参数数据(针对每个参数重复)
- (见下文)
blob size word
[0 .. 63]
:Blob 载荷大小(以字节为单位,不包括填充)
载荷流(可变大小)
- 二进制数据,使用零填充以对齐到 8 字节
带内大型 Blob 记录无元数据(blob 格式 = 1)
此类型包含记录本身中的 blob 数据,但不包含元数据。记录仅包含类别和名称。
该名称应足以标识 blob 中包含的数据类型。
格式
标题字词
[0 .. 3]
:记录类型 (15)[4 .. 35]
:记录大小(包括此字),以 8 字节的倍数表示[36 .. 39]
:大型记录类型 (0)[40 .. 43]
:blob 格式类型 (1)[44 .. 63]
:保留,必须为 0
设置标题格式
[0 .. 15]
:类别(字符串引用)[16 .. 31]
:名称(字符串引用)[32 .. 63]
:保留,必须为 0
类别串流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
blob size word
[0 .. 63]
:Blob 载荷大小(以字节为单位,不包括填充)
载荷流(可变大小)
- 二进制数据,使用零填充以对齐到 8 字节
参数类型
参数用于关联类型化的键值数据记录。它们与事件记录、用户空间对象记录和内核对象记录一起使用。
每个参数都由一个字词的标头和一个可变字词数的载荷组成。在许多情况下,标头本身就足以编码实参的内容。
参数类型如下:
参数标头
所有参数都包含此标头,该标头用于指定参数的类型、名称和大小,以及 32 位数据,其用途因参数类型而异。
格式
argument header word
[0 .. 3]
:参数类型[4 .. 15]
:参数大小(包括此字),以 8 字节的倍数表示[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:不定(如果未使用,则必须为零)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数为 null(参数类型 = 0)
表示仅显示名称而没有值的参数。
格式
argument header word
[0 .. 3]
:参数类型 (0)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
32 位有符号整数参数(参数类型 = 1)
表示 32 位有符号整数。
格式
argument header word
[0 .. 3]
:参数类型 (1)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:32 位有符号整数
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
32 位无符号整数参数(参数类型 = 2)
表示 32 位无符号整数。
格式
argument header word
[0 .. 3]
:参数类型 (2)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:32 位无符号整数
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
64 位有符号整数参数(参数类型 = 3)
表示 64 位有符号整数。如果值可容纳在 32 位内,请改用32 位有符号整数参数类型。
格式
argument header word
[0 .. 3]
:参数类型 (3)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数值字
[0 .. 63]
:64 位有符号整数
64 位无符号整数参数(参数类型 = 4)
表示 64 位无符号整数。如果值可容纳在 32 位内,请改用32 位无符号整数参数类型。
格式
argument header word
[0 .. 3]
:参数类型 (4)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数值字
[0 .. 63]
:64 位无符号整数
双精度浮点参数(参数类型 = 5)
表示双精度浮点数。
格式
argument header word
[0 .. 3]
:参数类型 (5)[4 .. 15]
:参数大小(包括此字),以 8 字节的倍数表示[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数值字
[0 .. 63]
:双精度浮点数
字符串参数(参数类型 = 6)
表示字符串值。
格式
argument header word
[0 .. 3]
:参数类型 (6)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 47]
:参数值(字符串引用)[48 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数值流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
指针参数(参数类型 = 7)
表示指针值。与同一指针关联的用户空间对象记录可以提供有关引用的其他信息。
格式
argument header word
[0 .. 3]
:参数类型 (7)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数值字
[0 .. 63]
:指针值
内核对象 ID 参数(参数类型 = 8)
表示 koid(内核对象 ID)。与同一 koid 关联的内核对象记录可以提供有关引用的更多信息。
格式
argument header word
[0 .. 3]
:参数类型 (8)[4 .. 15]
:参数大小(包括此字)为 8 字节的倍数[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:保留(必须为 0)
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节
参数值字
[0 .. 63]
:koid(内核对象 ID)
布尔值参数(参数类型 = 9)
表示布尔值。
格式
argument header word
[0 .. 3]
:参数类型 (9)[4 .. 15]
:参数大小(包括此字),以 8 字节的倍数表示[16 .. 31]
:参数名称(字符串引用)[32 .. 63]
:1 位填充为零
参数名称流(除非字符串引用表示内嵌字符串,否则省略)
- UTF-8 字符串,使用零填充以对齐到 8 字节