Sysmem 是一项 FIDL 服务,用于分配共享内存以供多个应用和硬件块使用。本文档介绍了 主要功能及其为系统提供的功能概览。
设计初衷
现代系统都有专用硬件块, 数据。以下是这些代码块的一些示例:
- 使用 GPU 渲染计算机图形。
- 使用硬件编解码器编码或解码视频。
- 使用相机和 DSP 拍摄高品质照片。
- 使用显示屏控制器的叠加引擎将图片合成到显示屏上。
- 使用 TPU 评估神经网络。
通常,我们希望创建在这些单独的硬件块之间传递数据的流水线。请参见以下示例:
- 使用硬件编解码器解码视频,并将其与在 GPU 上渲染的界面内容一起合成到显示屏上。
- 将神经网络应用于实时摄像头画面。
为了高效地完成这些操作并避免复制,驱动程序和应用必须同意 以及数据在内存中的位置。此协议允许一个单元的输出直接被下一个单元使用。硬件单元对这些属性有严格的限制,而且 确定哪种数据布局可实现最佳效果。
Sysmem 是一项全球性服务 分配缓冲区,以便满足所有约束条件。如果有多种格式 则可根据预期效果从这些方面进行选择。
Sysmem 缓冲区通常用于表示图片,并且 sysmem 对协商图片格式有特殊支持。不过,sysmem 接口也可以 用于音频或任何其他类型的数据。
分配缓冲区后,Sysmem 不会管理数据流。流水线中的应用负责相互协调,以确保同步。
分配流程(简化)
- 参与者连接到 fuchsia.sysmem2.Allocator 服务
- 一个参与者(称为发起者)会创建初始缓冲区收集令牌。
- 该参与者复制令牌,并将副本发送给其他参与者。
- 这些参与者还可以以递归方式复制和发送令牌, 所有参与者都收到了一个令牌。
- 每个参与者都会绑定其令牌以获取缓冲区集合。
- 每个参与者都对缓冲区收集设置约束
- Sysmem 会选择可满足所有限制条件的格式。只有在每个参与者都绑定了自己的令牌并对集合设置了约束条件后,才会发生这种情况。
- Sysmem 使用该格式分配多个缓冲区。
- 参与者从 sysmem 检索缓冲区以及有关分配的格式的信息。
sysmem 返回的信息是映像的一组约束条件, 所有格式。
此时,参与者可以使用具有已分配格式的缓冲区, 它们之间的数据传输 参与者。由于在一个缓冲区中可以使用多种尺寸的图片, 参与者必须共同选择图片大小 确定精确的图片格式。这样,流水线就可以 而无需重新分配缓冲区。
如果需要向已完成约束条件协商和分配的现有集合添加新参与者,则可以将新令牌附加到缓冲区集合。新参与者的 约束条件, 或者逻辑分配(从新参与者的角度来看)失败。 为了提高成功添加新参与者的几率,初始分配期间的参与者之一可以将令牌标记为可有可无。这样,令牌便可用于指定替代约束条件,以便缓冲区集合日后能够容纳具有相同约束条件的新参与者。
缓冲区销毁
缓冲区销毁是异步进行的。
如需等待旧集合的旧缓冲区完全删除(可选设置截止期限),请参阅 AttachLifetimeTracking。
缓冲区销毁序列在缓冲区收集失败时开始。在
正常/成功的情况,即此“失败”通常
(通常是发起者)会在未发送
Release。目前,集合专用渠道包括 BufferCollectionToken、BufferCollection 和 BufferCollectionTokenGroup 渠道。
当集合进入失败状态时,sysmem 服务器将关闭 所有特定集合渠道的服务器端。在参与者完成清理之前,所有分配的 VMO 都仍然可用(请参阅下方列表)。
此时,所有参与者应该都会很快注意到(直接或
通过其他足够信任的参与者间接)收集特定集合
通道服务器端关闭(在客户端发出 ZX_CHANNEL_PEER_CLOSED 信号)。
然后,每个参与者都确保尽可能多的缓冲区满足以下清理条件列表。在极少数情况下,保留少量缓冲区一段时间是有意义的,例如,在使用新集合的新视频帧可用之前,将上一个视频帧保留在屏幕上。
必须先移除对缓冲区的所有引用,然后 sysmem 才会销毁该缓冲区并 以便重复使用其中包括:
- VMO 的句柄。
- VMO 的 CPU 映射。
- VMO 的子 VMO。
- 供硬件使用的 VMO 的 Pin(固定)。
- 通道到包含这些 VMOs 的缓冲区集合。系统内存
无论该通道是由
客户端或服务器此项不适用于之前发送过
SetWeak且仍处于打开状态的渠道。
在非首选且不太常见的模型下,所有参与者可能会在分配后不久关闭所有收集专用渠道(先关闭或不先关闭 Release),这会提前触发收集失败(由于没有剩余的收集专用渠道),但之后参与者可能会继续使用这些 VMO 一段时间,即使收集已“失败”也是如此。以后再说
它们使用单独的机制来了解何时需要清理 VMO(请参阅
)。
从技术上讲,非首选模型是可行的,但可以让集合
使系统内存检查数据不够清晰 / 实用。
不过,在极少数情况下,这种非首选模型
适应其他协议 / 接口施加的限制。如果考虑
对于此模型,首先考虑让一个参与者发送 Release,
关闭其特定集合的渠道,然后获知收集失败
通过其他(充分信任的)参与者间接达成;这样,总的
设置依然符合上述首选模式。如果考虑采用此模型的唯一原因是允许增量缓冲区取消分配,请改用 SetWeak。
高级用法
后备限制和/或可选参与者
BufferCollectionTokenGroup 用于更多
整个参与者可选 / 尽力而为的复杂情况;
如果存在与首选的不太严格的回退限制条件不同
更为严格的限制条件(例如,出于性能方面的原因)。
在分配期间,系统只会选择组直接下的一个子令牌(以及从该令牌开始的子树),并优先选择组的第一个子令牌等。
允许在群组下创建令牌下的群组(等)。
分配期间尝试的组子项选择组合总数上限;如果达到此上限,请随时与我们联系,讨论替代方案。
这是高级用法,与大多数参与者都没有直接关系。请参阅 BufferCollectionTokenGroup 的文档。
故障隔离和/或参与者迟到
SetDispensable 和 AttachToken 消息可用于创建隔离故障的子树(由令牌复制父子关系定义),并在原始子树实例发生故障后,可能将该子树替换为新的子树实例,而不会导致根实例发生故障。
发起者创建的第一个令牌是 创建根目录;之后创建的合集渠道 该标记仍会被视为树状结构的根节点(不同的协议、 而是相同的“节点”)。
替换子树时,新的子树参与者会看到看似正常的分配序列,但实际上,它们正在“加入”一个“正在进行”的缓冲区集合。
使用 AttachToken 不需要先使用 SetDispensable。
目前,AttachToken 要求集合
足够的缓冲区以满足新连接的参与者实例的需求。
这是一种高级用法,与大多数参与者没有直接关系。请参阅 SetDispensable 和 AttachToken 的文档。
术语库
缓冲区
缓冲区表示应用的单个图像或其他内存块 名称。Sysmem 目前对每个缓冲区使用一个 VMO。客户端可以 将内存映射到 CPU 上,或将其固定在硬件上 。
参与者
参与者是指想要访问缓冲区的任何应用或驱动程序。所有参与者都必须连接到 sysmem 以协商内存格式。
映像格式
图片格式是呈现图片所需的一系列属性, 将内存解释为一组像素。例如,它包括像素格式、宽度和高度、行间行高(以字节为单位)和色彩空间。
缓冲区设置
缓冲区设置是对 缓冲区的属性。其中包括缓存信息 添加参与者在访问内存时可能需要使用的属性对于图片,缓冲区设置还具有图片格式。
缓冲区设置不包含具体的内存地址,因此多个 可以使用相同的缓冲区设置。
堆
堆表示系统上一种特定类型的内存。系统可能具有多个具有不同性能特性的堆。某些堆可能只能通过一部分硬件使用 应用。
某些堆可能无法从 CPU 访问。对于这些堆,表示缓冲区的 VMO 无法直接使用,而是用作键。如需使用该缓冲区,应用必须将其 VMO 句柄发送到堆驱动程序,而堆驱动程序可以返回有关要使用哪种内存的信息。
堆示例:
- 主系统内存。
- 独立显卡上的显存。
- 系统内存的一个划分区域,仅供 硬件。
约束条件
限制用于指定参与者可以使用的 BufferSettings 集。参与者通常会在一组中指定多个可能的缓冲设置。 这使得系统内存能够灵活选择任意 降低没有可满足限制条件的设置的风险 所有参与者的评论。
协商
协商是指 sysmem 查看参与者的所有约束条件,并选择适用于所有参与者的缓冲区设置的过程。如果可以使用多种设置,sysmem 可以使用有关客户端将如何使用缓冲区以及系统架构的信息来选择最佳设置。
缓冲区收集
缓冲区集合是一组包含所有缓冲区的 相同的缓冲区设置。系统会在 一次。多个参与者可以对同一缓冲区集合打开 FIDL 通道。