协议
分配器
在 fuchsia.sysmem/allocator.fidl 中定义
分配系统内存缓冲区。
AllocateNonSharedCollection
代表单个客户端(也称为发起者)分配 BufferCollection,该客户端也是唯一的参与者(从 sysmem 的角度来看)。
此调用主要用于临时/测试目的。此调用跳过了 BufferCollectionToken 阶段,因此无法允许其他参与者指定其约束条件。
我们建议真实的客户端改用 AllocateSharedCollection(),并让相关参与者直接将自己的约束条件传达给系统内存。
collection_request
是 BufferCollection FIDL 通道的服务器端。客户端可以在此通道的客户端端调用 SetConstraints(),然后调用 WaitForBuffersAlloud(),以指定限制条件,然后确定成功/失败并获取 BufferCollection 的 BufferCollectionInfo_2。使用 BufferCollection 时,客户端还应使此通道的客户端端保持打开状态,并应尽快注意到此通道关闭和停止使用 BufferCollection 的时间。
请求
名称 | 类型 |
---|---|
collection_request |
server_end<BufferCollection>
|
AllocateSharedCollection
创建一个可在参与者之间共享的逻辑 BufferCollectionToken(使用 BufferCollectionToken.Duplicate()),然后使用 BindSharedCollection() 将其转换为 BufferCollection。
使用缓冲区填充 BufferCollection 的成功/失败是通过 BufferCollection 接口确定的。
请求
名称 | 类型 |
---|---|
token_request |
server_end<BufferCollectionToken>
|
BindSharedCollection
将 BufferCollectionToken 转换为与逻辑 BufferCollection 的连接。BufferCollection 中尚未填充缓冲区,参与者还必须通过 buffer_collection 的客户端端发送 SetConstraints()。
从通过 AllocateSharedCollection() 创建的逻辑 BufferCollectionToken 中复制的所有 BufferCollectionToken 必须通过 BindSharedCollection() 转换为对逻辑 BufferCollection 进行填充之前。
token
表示某个通道的客户端端点,该通道的服务器端已使用 AllocateSharedCollection 发送到系统管理,或者其服务器端已使用 BufferCollectionToken.Duplicate() 发送到 Sysmem。该令牌将用于“交换”到逻辑 BufferCollection 的通道。
buffer_collection_request
是 BufferCollection 通道的服务器端。发件人照常保留客户端。BufferCollection 通道是单个参与者与逻辑 BufferCollection 之间的连接。通常有其他参与者,他们拥有自己的逻辑 BufferCollection 的 BufferCollection 通道。
请求
名称 | 类型 |
---|---|
token |
BufferCollectionToken
|
buffer_collection_request |
server_end<BufferCollection>
|
ConnectToSysmem2Allocator
这允许在给定 sysmem(1) Allocator
的情况下创建 sysmem2 Allocator
。
这主要在以下情况下非常有用:库代码传递给 sysmem(1) 分配器,但库代码已更新为使用 sysmem2。通常,该库会提供传入 sysmem2 Allocator
的方法,但客户端代码并不总是在同一个代码库中,因此此消息允许该库暂时接受 sysmem(1) 分配器。
通过 SetDebugClientInfo
设置的信息(如果有)会复制到 sysmem2 Allocator
。
请求
名称 | 类型 |
---|---|
allocator_request |
server_end<fuchsia.sysmem2/Allocator>
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可以使用这些信息来调试泄漏内存并挂起等待约束。|name| 可以是任意字符串,但最好使用当前进程名称(请参阅 fsl::GetCurrentProcessName())。|id| 可以是任意 ID,但最好使用当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())。
此信息会传播到从该分配器使用 BindSharedCollection() 或 AllocateNonSharedCollection() 创建的所有 BufferCollection。这不会影响 BufferCollectionTokens,因为它们通常是跨进程传递的,应手动管理其名称。
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
ValidateBufferCollectionToken
验证 Sysmem 服务器是否知道 BufferCollectionToken。
如果客户端代码想要早点(到目前为止)知道传入令牌是否有效,那么可以使用此方法,即在 BufferCollectionToken.Duplicate() + BufferCollectionToken.Sync() 之后才调用 BindSharedCollection()。
对 Sysmem 未知的令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永久挂起。
鉴于任何参与者丢弃其 BufferCollectionToken 或 BufferCollection 时,传入的令牌随时可能失效,因此建议客户端代码的作者考虑不要调用 VerifiedBufferCollectionToken(),而是处理所有 BufferCollectionToken.Duplicate() 和 BindSharedCollection() 之后的 BufferCollection.Sync() 异步故障(在将任何重复的令牌发送到其他进程之前)。
无论此调用的结果如何,此调用对具有所引用 koid 的令牌都没有影响。
此调用产生的真实结果不能保证令牌在之后的任何时长内仍然有效。
客户端代码将在客户端的令牌句柄上执行 zx_object_get_info(),传递 ZX_INFO_HANDLE_BASIC 并获取 related_koid,后者随后又被传递到 VerifyBufferCollectionToken()。
如果 VerifiedBufferCollectionToken() 返回 true,则说明在 sysmem 服务器处理调用时该令牌是已知的,但当客户端代码收到响应时,令牌可能不再有效/已知。
如果 ValidBufferCollectionToken() 返回 false,则表示 sysmem 服务器在处理调用时不知道该令牌,但在客户端代码收到响应时,该令牌可能已经知道。但是,由于令牌来源应在将令牌发送到客户端代码之前将令牌同步到 sysmem,因此不需要客户端代码,以降低令牌可能延迟获知的可能性。
如果调用 VerifiedBufferCollectionToken() 以某种方式失败,FIDL 层中将会出现 zx_status_t。
token_server_koid
是通道(可能是 BufferCollectionToken 通道)的服务器端的 koid。这可以从 zx_object_get_info() ZX_INFO_HANDLE_BASIC related_koid 中获取。
请求
名称 | 类型 |
---|---|
token_server_koid |
zx/Koid
|
响应
名称 | 类型 |
---|---|
is_known |
bool
|
BufferCollection
在 fuchsia.sysmem/collection.fidl 中定义
BufferCollection 是指从参与者直接到 sysmem 的连接,属于逻辑 BufferCollection;通常逻辑 BufferCollection 与其他参与者共享。换句话说,BufferCollection 接口的实例是“逻辑缓冲区集合”的视图。
此连接旨在方便异步指示何时填充了逻辑 BufferCollection。
此外,该通道被服务器关闭表示客户端应尽快关闭从 BufferCollection 获取的所有 VMO 句柄。
此外,此接口将来可能会允许以其他方式指定限制条件,并且可能允许在一定程度上来回协商限制条件。
此接口将来可能允许每个 BufferCollection 超过 64 个 VMO 句柄,但目前的限制为 64 个。
此接口将来可能允许分配/取消分配单个缓冲区。
有些发起者可能会等待一小段时间,直到所有旧的逻辑 BufferCollection VMO 句柄都关闭(或直到短暂的持续时间超时),然后再分配新的 BufferCollection,以帮助控制物理内存碎片并避免新旧集合的缓冲区分配生命周期重叠。集合可以足够大,因此有必要(及时避免分配重叠)。
AttachLifetimeTracking
AttachLifetimeTracking:
AttachLifetimeTracking() 旨在允许客户端等待,直到旧的逻辑缓冲区收集完全或大部分被取消分配,然后再尝试分配新的逻辑缓冲区集合。
将 eventpair 端点附加到逻辑缓冲区集合,以便在分配的缓冲区数量减少到“buffers_remaining”时,server_end 会关闭。server_end 在逻辑分配完成之前不会关闭。
如果逻辑分配失败,例如对于连接的子树(使用 AttachToken()),服务器_end 将在失败期间关闭,无论整个逻辑缓冲区集合中可能分配的缓冲区数是多少。
此事件发出的生命周期包括对已分配缓冲区的异步清理,并且此异步清理必须等到所有缓冲区的 VMO 句柄都关闭这些 VMO 句柄后才会发生。因此,在等待 ZX_EVENTPAIR_PEER_CLOSED 收到信号后,客户端应小心避免被永久阻止,尤其是在使用逻辑缓冲区收集的任何参与者可信度较低或可靠性较低的情况下。
Buffers_remaining 参数允许等待除 buffers_remaining 之外的所有缓冲区完全释放。这在以下情况下非常有用:为避免关闭已知数量的缓冲区,以便继续使用数据,例如,即使视频串流使用的是受保护的输出缓冲区,也能保留界面中显示的最后一张视频图片。确定无需关闭即可保留的缓冲区数量(至少目前)不在 BufferCollection 接口的范围内,但该值通常介于 0-2 的范围内。
此机制旨在与提供类似 AttachLifetimeTracking() 机制的其他协议兼容,因为可将相同事件的重复项发送到多个 AttachLifetimeTracking(),并在满足所有生命周期条件(所有副本持有者均已关闭句柄)时发出信号,通知 ZX_EVENTPAIR_PEER_CLOSED。
您无法取消连接。关闭事件对的客户端端不会减少待处理连接的数量。
关闭客户端端不会导致服务器执行任何操作。 如果服务器从客户端监听事件,则仅用于调试日志记录。
服务器有意不“信任”客户端发出的任何信号。此机制有意仅使用 ZX_EVENTPAIR_PEER_CLOSED,这种模式无法提前触发,并且仅在 server_end 的所有句柄均关闭时触发。没有任何与任何其他信号位相关联的含义,客户端在功能上应忽略事件对一端或其对等端的任何其他信号位。
server_end 可能缺少 ZX_RIGHT_SIGNAL 或 ZX_RIGHT_SIGNAL_PEER,但必须具有 ZX_RIGHT_DUPLICATE(并且必须具有 ZX_RIGHT_TRANSFER 才能传输,且不会导致 CodecFactory 通道故障)。
请求
名称 | 类型 |
---|---|
server_end |
handle<eventpair>
|
buffers_remaining |
uint32
|
AttachToken
创建新令牌,用于尝试在现有集合的缓冲区计数、约束条件和参与者允许的情况下将新参与者添加到现有集合。
这对于替换失败的参与者和/或在分配缓冲区后添加/重新添加参与者时很有用。
附加的令牌 / 集合的失败不会传播到所附加令牌的父级。失败会从可分配令牌的常规子节点传播到可分配令牌。如果附加了子项,或者子项可分配且在逻辑分配之后发生故障,则子项故障将无法到达其父项。
在某些情况下,发起者可能会选择最初为参与者的给定实例使用可分配令牌,之后如果该参与者的第一个实例失败,该参与者的第二个实例将获得使用 AttachToken() 创建的令牌。
从 BufferCollectionToken 通道客户端的角度来看,该令牌的作用与任何其他令牌类似。客户端可以根据需要 Duplicate() 令牌,并将该令牌发送到其他进程。令牌应照常通过调用 BindSharedCollection() 转换为 BufferCollection 通道。应在该 BufferCollection 通道上调用 SetConstraints()。
WaitForBuffersAlloaded() 的结果表示新参与者的约束条件可通过使用现有缓冲区收集、已建立的 BufferCollectionInfo(包括图片格式限制条件)以及已经存在的其他参与者及其缓冲区计数来满足。失败结果意味着,无法使用现有缓冲区集合及其已在逻辑上分配的参与者来满足新参与者的约束条件。创建新集合可能会满足所有参与者的约束条件(假设使用 SetDispensable() 代替 AttachToken() 或者使用普通令牌)。
使用 AttachToken() 创建的令牌执行约束聚合,其中当前对缓冲区集合应用的所有约束条件,以及考虑中的附加令牌,以及附加令牌下本身不是附加令牌或此类令牌下的子令牌。
将 Buffer_count 分配给 min_buffer_count_for_camping 等时,将优先投放,但子项在其所有父项都发送 SetConstraints() 之前不能进行逻辑分配。
另请参阅 SetDispensable(),与 AttachToken() 不同,它让创建的令牌和子项及其父级参与约束汇总。
您必须先将新创建的令牌 Sync() 到 sysmem,然后才能将新令牌传递给 BindSharedCollection()。您可以使用此 BufferCollection 的 BufferCollection.Sync() 实现新令牌的 Sync()。在新令牌上,BufferCollectionToken.Sync() 也可以起作用。通过新创建的令牌发送任何 BufferCollectionToken.Duplicate() 消息后,可以启动 BufferCollectionToken.Sync(),以便通过单次往返将这些额外的令牌同步到 sysmem。
Rights_attenuation_mask 值不会导致衰减(请注意,0 不在此列表中;0 会在系统日志中输出 ERROR,以帮助诊断客户端代码中的 bug):
- ZX_RIGHT_SAME_RIGHTS(首选)
- 0xFFFFFFFF(计算衰减掩码时是合理的)
请求
名称 | 类型 |
---|---|
rights_attenuation_mask |
uint32
|
token_request |
server_end<BufferCollectionToken>
|
CheckBuffersAllocated
如果缓冲区收集已分配或失败,则返回的结果代码与 WaitForBuffersAlloud 返回的结果代码相同;如果 WaitForBuffersAlloud 会进行阻塞,则返回 ZX_ERR_UNAVAILABLE
。
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
status |
zx/Status
|
关闭
在 BufferCollectionToken 通道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地关闭该令牌(然后立即或稍后关闭该通道,以响应服务器关闭其端),从而避免逻辑缓冲区收集失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,服务器通过使整个逻辑缓冲区收集失败来处理 BufferCollection 的意外故障。部分原因在于在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者想要彻底关闭 BufferCollection 视图,而不会导致逻辑缓冲区收集失败,则可以在关闭 BufferCollection 通道的客户端端之前发送 Close()。如果这是最后一个 BufferCollection 视图,逻辑缓冲区收集仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前,则缓冲区集合将不需要此节点的约束来分配。如果在 SetConstraints() 之后,约束条件将保留并连同任何后续逻辑分配一起聚合,尽管缺少通道连接。
在 BufferCollectionTokenGroup 通道上:
默认情况下,BufferCollectionTokenGroup 出现意外故障将触发逻辑 BufferCollectionTokenGroup 故障,并将故障传播至其父级。若要关闭 BufferCollectionTokenGroup 通道而不使逻辑组失败或传播故障,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,那么即使发生 Close(),逻辑缓冲区收集仍会失败(因为系统管理器无法确定是否创建了所有相关的子项,因此是否将所有相关约束条件都提供给系统尚不清楚)。如果 Close() 发生在 AllChildrenPresent() 之后,则子节点及其所有约束条件都会保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态时一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
DeprecatedClose
请求
<EMPTY>
DeprecatedSetDebugClientInfo
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
DeprecatedSetName
请求
名称 | 类型 |
---|---|
priority |
uint32
|
name |
string[64]
|
DeprecatedSync
请求
<EMPTY>
响应
<EMPTY>
GetAuxBuffers
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
status |
zx/Status
|
buffer_collection_info_aux_buffers |
BufferCollectionInfo_2
|
GetNodeRef
这将获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端将无权发出此事件,因为此句柄只能用作客户端从此节点获取此句柄的证明。
由于这是一个 get 而非 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能位于不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
IsAlternateFor
这将检查调用节点是否位于某个子树中,该子树的根位置为与传入 node_ref 相关的共同父 BufferCollectionTokenGroup 的不同子令牌。
此调用旨在协助准入控制去重和调试。
必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取 node_ref。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时调用 GetNodeRef()。
如果由于调用令牌的提供者可能存在恶意/不可信,导致调用令牌实际上可能根本不是有效令牌,请先调用 VerifyBufferCollectionToken(),而不是在 IsAlternateFor() 因调用令牌不是真实令牌(并非真正与 sysmem 通信)而一直未响应的情况下,调用 VerifyBufferCollectionToken(),而不是无限期地陷入困境。另一种方法是先使用此令牌调用 BindSharedCollection,该令牌也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示未在与调用节点相同的逻辑缓冲区集合中找到 node_ref。在逻辑分配之前以及同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 至少会一直存在,直到逻辑分配(包括已完成 Close() 和关闭其通道的节点)才继续存在,并且如果 ZX_ERR_NOT_FOUND 尚未返回逻辑分配,则此节点不会返回。在逻辑分配之后或在其他逻辑分配子树中,还有其他可能造成此错误的原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此 Node 逻辑分配分隔)可能会导致其子树失效而删除这些节点,或者可能存在 BufferCollectionTokenGroup 存在,并且可能会选择与 node_ref 所在的子树不同的子树,从而导致 Node_ref 被删除。仅当系统使用 Close() 且节点的子树尚未失败时,系统才会在节点没有相应的通道之后保留该节点。出现此错误的另一个原因是,node_ref 是具有足够权限的事件对句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是事件对句柄,或者没有在实际 node_ref 上预期的权限。
此调用不会返回其他失败的状态代码。不过,sysmem 将来可能会添加其他代码,以便客户端应对所有失败的状态代码进行合理的默认处理。
成功后,is_alternate 具有以下含义:
- true - 调用节点与 node_ref 节点之间的第一个父节点是 BufferCollectionTokenGroup。这意味着,调用的 Node 和 node_ref 节点不会同时应用其这两项约束条件,而是 sysmem 会选择其中一个约束条件,但绝不会同时应用两者。这是因为在逻辑分配期间只会选择 BufferCollectionTokenGroup 的一个子项,并且只有该子项的子树对约束聚合有贡献。
- false - 调用节点和 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同的父节点是 BufferCollectionToken 或 BufferCollection(无论是否为 Close()ed 或 Close()ed)。这意味着,如果任何涉及的父 BufferCollectionTokenGroup 同时选择了这两个节点,则调用节点和 node_ref 节点可以在逻辑分配的约束聚合期间应用它们的约束条件。在这种情况下,没有 BufferCollectionTokenGroup 可直接阻止选择两个节点及其约束条件进行汇总,但即使值为 false,如果一个或两个 Node 具有直接或间接父 BufferCollectionTokenGroup,且该子树选择除调用 Node 或
请求
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
响应
名称 | 类型 |
---|---|
payload |
Node_IsAlternateFor_Result
|
SetConstraints
向逻辑 BufferCollection 提供 BufferCollectionConstraints。
一个参与者只能调用 SetConstraints() 一次。
有时,发起者只是一个参与者,因为只希望关注成功/失败是否填充缓冲区,以及在失败时关注 zx.Status。在这种情况下,has_constraints
可以为 false,并忽略 constraints
。
系统不会向发送 null 约束条件的客户端提供 VMO 句柄,对于不需要 VMO 句柄的发起者而言,这可能是有意为之。没有 VMO 句柄不会阻止发起者调整缓冲区的哪个部分被视为有效和相似,但无论发起者出于何种原因,无论发起者的参与程度如何,如果逻辑 BufferCollection 需要消失,发起者都不能将 VMO 句柄保持开启状态,以防止逻辑 BufferCollection 被清理。
如需尝试填充缓冲区,BufferCollection 客户端通道的所有持有者都需要在 sysmem 尝试分配缓冲区之前调用 SetConstraints()。
如果为 false,则为 has_constraints
,则这些约束实际上为 null 并忽略 constraints
。null 约束的发送方不会在 BufferCollectionInfo 中获得任何 VMO 句柄,但仍可以看到已分配的缓冲区数量,并且仍然可以按相应 buffer_index 来引用缓冲区。
constraints
是对缓冲区集合的约束条件。
请求
名称 | 类型 |
---|---|
has_constraints |
bool
|
constraints |
BufferCollectionConstraints
|
SetConstraintsAuxBuffers
请求
名称 | 类型 |
---|---|
constraints |
BufferCollectionConstraintsAuxBuffers
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可以使用这些信息来调试泄漏内存并挂起等待约束。|name| 可以是任意字符串,但最好使用当前进程名称(请参阅 fsl::GetCurrentProcessName())。|id| 可以是任意 ID,但最好使用当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())。
在启用详细日志记录功能时,也会使用该选项(请参阅 SetVerboseLogging()),以指明哪个客户端首先关闭其通道,进而导致子树故障(如果子树的用途结束,这可能是正常的,但如果发生的时间早于预期,客户端渠道专用名称有助于从 sysmem 的角度诊断故障首先来自何处)。
默认情况下(除非被此消息或使用 Allocator.SetDebugClientInfo() 替换),否则节点会在创建子节点时从其父节点复制信息。虽然这样做总比什么都好,但每个参与者通常最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 将信息与当前客户端直接相关。此外,SetVerboseLogging() 可用于帮助消除歧义,确定某个节点是否涉嫌包含从其父节点复制的信息。
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制条件,Ssmem 就会记录一条警告。客户端可以调用此方法来在输出日志时进行更改。如果由多个客户端设置了截止期限,则未指定截止期限的生效时间。
请求
名称 | 类型 |
---|---|
deadline |
zx/Time
|
SetName
设置此缓冲区集合中的 VMO 的名称。此名称可能会被截短。该名称只会影响在设置后分配的虚拟机 OS,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值越大,优先级越高。
请求
名称 | 类型 |
---|---|
priority |
uint32
|
name |
string[64]
|
SetVerboseLogging
详细日志记录功能包括从每个客户端通过 SetConstraints() 设置的约束、通过 SetDebugClientInfo() 设置的信息,以及节点树的结构。
通常,当汇总失败时,sysmem 仅输出一行投诉,并且仅会显示汇总失败的具体详细原因,并提供最少的上下文。虽然这通常足以诊断出问题(如果仅进行了细微更改,并且系统在小更改之前就已正常运行),但对于首次获取新的缓冲区集合来说,这通常不是特别有帮助。尤其是对于涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树,详细日志记录有助于诊断树的外观及其逻辑分配失败的原因,或者树或子树的失败速度比预期更快的原因。
如果仅在少量缓冲区集合中启用额外日志记录,那么从性能的角度来看,额外日志记录是可以接受的。如果我们没有追踪错误,则不应发送此邮件。
如果太多参与者将详细日志记录功能保持启用状态,我们最终可能需要要求通过一些其他设置允许系统级系统内存详细日志记录功能,以避免系统因此消息而过多地向日志发送垃圾内容。
如果我们对某个节点的信任不够充分,无法允许其启用详细日志记录功能,则由于与节点关联的有意政策,这对某些节点而言可能是一个 NOP。
请求
<EMPTY>
同步
确保已在服务器端收到之前的消息,包括令牌、集合或组上的 Duplicate() 消息。
对无效/无效的 sysmem 令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永久挂起。若要以一次往返为代价来降低恶意/虚假 BufferCollectionToken 的可能性,请参阅 VerifyBufferCollectionToken()。另一种方法是将令牌传递给 BindSharedCollection(),后者还会在将令牌交换为 BufferCollection 通道时验证令牌,然后可以使用 BufferCollection Sync()。
在 Sync() 之后,您可以放心地将 token_request 的客户端端发送给其他参与者,并知道在另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括等待每个 token.Duplicate() 完成(在每个令牌之后单独调用 token.Sync()),或者在通过 BindSharedCollection() 上交令牌后在 BufferCollection 上调用 Sync()。
另一种缓解措施是避免对令牌调用 Sync(),改为在原始令牌无效时处理 BufferCollection.Sync() 可能失败的问题。从性能的角度来看,这是更可取的方法,但要求客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将重复令牌转换为 BufferCollection 并从 BufferCollection.Sync() 收到成功响应之后。
在可行的情况下,最好改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,调用方必须已经知道此令牌有效/有效,否则 BufferCollectionToken.Sync() 可能会永久挂起。如果还不知道令牌是否有效,请先查看 RestrictBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
WaitForBuffersAllocated
分配缓冲区后,此请求会完成;如果尝试分配失败,则会响应一些失败详细信息。
在分配缓冲区之前必须发生以下情况:
- 逻辑 BufferCollectionToken 的所有 BufferCollectionToken 必须通过 BindSharedCollection() 上交。
- 必须向逻辑 BufferCollection 的所有 BufferCollection 发送 SetConstraints()。
如果成功,则返回 ZX_OK
。
如果请求有效但因资源耗尽而无法完成,则返回 ZX_ERR_NO_MEMORY
。如果不允许调用方获取其请求的缓冲区,则返回 ZX_ERR_ACCESS_DENIED
。如果请求格式错误,则返回 ZX_ERR_INVALID_ARGS
。如果请求有效但因硬件限制而无法得到满足,则返回 ZX_ERR_NOT_SUPPORTED
。
buffer_collection_info
包含 VMO 句柄和其他相关信息。
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
status |
zx/Status
|
buffer_collection_info |
BufferCollectionInfo_2
|
BufferCollectionToken
在 fuchsia.sysmem/collection.fidl 中定义
BufferCollectionToken 不是 BufferCollection,而是在分配 BufferCollection 之前标识潜在的共享 BufferCollection 的方法。
我们为 BufferCollectionToken 使用一个通道,而不是单个事件对(对),因为通过这种方式我们可以检测到错误情况,例如参与者在创建过程中终止。
关闭
在 BufferCollectionToken 通道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地关闭该令牌(然后立即或稍后关闭该通道,以响应服务器关闭其端),从而避免逻辑缓冲区收集失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,服务器通过使整个逻辑缓冲区收集失败来处理 BufferCollection 的意外故障。部分原因在于在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者想要彻底关闭 BufferCollection 视图,而不会导致逻辑缓冲区收集失败,则可以在关闭 BufferCollection 通道的客户端端之前发送 Close()。如果这是最后一个 BufferCollection 视图,逻辑缓冲区收集仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前,则缓冲区集合将不需要此节点的约束来分配。如果在 SetConstraints() 之后,约束条件将保留并连同任何后续逻辑分配一起聚合,尽管缺少通道连接。
在 BufferCollectionTokenGroup 通道上:
默认情况下,BufferCollectionTokenGroup 出现意外故障将触发逻辑 BufferCollectionTokenGroup 故障,并将故障传播至其父级。若要关闭 BufferCollectionTokenGroup 通道而不使逻辑组失败或传播故障,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,那么即使发生 Close(),逻辑缓冲区收集仍会失败(因为系统管理器无法确定是否创建了所有相关的子项,因此是否将所有相关约束条件都提供给系统尚不清楚)。如果 Close() 发生在 AllChildrenPresent() 之后,则子节点及其所有约束条件都会保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态时一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
CreateBufferCollectionTokenGroup
大多数 sysmem 客户端和许多参与者不需要关注此消息或一般 BufferCollectionTokenGroup。
BufferCollectionTokenGroup 用于在 N 个子令牌中创建 1 个 N OR 。汇总期间未选择的子令牌将会失败(关闭),当其 BufferCollection 通道客户端端点看到 PEER_CLOSED 时,潜在参与者应该注意到这一点,从而允许参与者清理最终未发生的推测性使用(类似于正常的 BufferCollection 服务器端在逻辑缓冲区收集失败时关闭)。
请参阅关于协议 BufferCollectionTokenGroup 的注释。
为此,可将任何要应用于整个群组的 Rights_attenuation_mask 或 AttachToken()/SetDispensable() 使用作为该组的直接父级的令牌来实现。
group_request - sysmem 提供的 BufferCollectionTokenGroup 通道的服务器端。
请求
名称 | 类型 |
---|---|
group_request |
server_end<BufferCollectionTokenGroup>
|
DeprecatedClose
请求
<EMPTY>
DeprecatedSetDebugClientInfo
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
DeprecatedSetDebugTimeoutLogDeadline
请求
名称 | 类型 |
---|---|
deadline |
zx/Time
|
DeprecatedSetName
请求
名称 | 类型 |
---|---|
priority |
uint32
|
name |
string[64]
|
DeprecatedSync
请求
<EMPTY>
响应
<EMPTY>
复制
此方法可用于在创建共享 BufferCollection 之前添加参与者。只有在不希望系统在每次副本中等待系统响应时,才应该使用它来代替 DuplicateSync。
发送一条或多条 Duplicate() 消息之后,在将创建的令牌发送给其他参与者(或其他分配器通道)之前,客户端应发送一个 Sync() 并等待其响应。可以对令牌执行 Sync() 调用,也可以在通过将此令牌传递给 BindSharedCollection() 所获得的 BufferCollection 上进行 Sync() 调用。任何一项都可以确保服务器先知道通过 Duplicate() 创建的令牌,然后再通过单独的分配器渠道将令牌发送到服务器。
所有令牌都必须通过 BindSharedCollection() 或 Close() 上交,才能成功创建 BufferCollection。
当客户端调用 BindSharedCollection() 以提交 BufferCollectionToken 时,服务器会先处理所有 Duplicate() 消息,然后再关闭 BufferCollectionToken。这样,客户端就可以 Duplicate() ,立即使用 BindSharedCollection 提交 BufferCollectionToken,然后将 token_request 的客户端端转移到另一个参与者,服务器在认为此 BufferCollectionToken 完全关闭之前,会发现 token_request 的存在。
此掩码中为零的 rights_attenuation_mask
权限位将不存在于可通过 token_request 的客户端端获取的缓冲区 VMO 权限中。这样,发起者或中间参与者就可以减少参与者享有的权利。但这并不会让参与者获得自己尚未拥有的权利。值 ZX_RIGHT_SAME_RIGHTS 可用于指定不应应用衰减。
Rights_attenuation_mask 的值不会导致衰减:
- ZX_RIGHT_SAME_RIGHTS(首选)
- 0xFFFFFFFF(计算衰减掩码时是合理的)
- 0(已弃用 - 请勿使用 0 - ERROR 会写入日志)
token_request
是 BufferCollectionToken 通道的服务器端。
此通道的客户端是创建共享 BufferCollection 的另一个参与者。
请求
名称 | 类型 |
---|---|
rights_attenuation_mask |
uint32
|
token_request |
server_end<BufferCollectionToken>
|
DuplicateSync
此方法可用于在创建共享 BufferCollection 之前添加更多参与者。系统将为 rights_attenuation_masks
数组中的每个条目返回一个新令牌。返回值是每个新参与者令牌的客户端结束。
如果由于调用令牌提供者可能存在恶意/不可信,发起调用的令牌实际上可能根本不是有效令牌,请考虑先使用 VerifyBufferCollectionToken(),而不是由于调用令牌不是真实令牌而导致 DuplicateSync() 从未响应,因此可能无限期地卡住不下。
与 Duplicate() 不同,调用此方法后不需要 Sync()(请参阅“协议节点”)。
所有令牌都必须通过 BindSharedCollection() 或 Close() 上交,才能成功创建 BufferCollection。
在 rights_attenuation_masks
的每个条目中,可通过相应返回的令牌获取的缓冲区 VMO 权限中不存在零权限位。这样,发起者或中间参与者就可以减少参与者享有的权利。但这并不会让参与者获得自己尚未拥有的权利。值 ZX_RIGHT_SAME_RIGHTS 可用于指定不应应用衰减。
请求
名称 | 类型 |
---|---|
rights_attenuation_masks |
vector<zx/Rights>[64]
|
响应
名称 | 类型 |
---|---|
tokens |
vector<BufferCollectionToken>[64]
|
GetNodeRef
这将获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端将无权发出此事件,因为此句柄只能用作客户端从此节点获取此句柄的证明。
由于这是一个 get 而非 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能位于不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
IsAlternateFor
这将检查调用节点是否位于某个子树中,该子树的根位置为与传入 node_ref 相关的共同父 BufferCollectionTokenGroup 的不同子令牌。
此调用旨在协助准入控制去重和调试。
必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取 node_ref。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时调用 GetNodeRef()。
如果由于调用令牌的提供者可能存在恶意/不可信,导致调用令牌实际上可能根本不是有效令牌,请先调用 VerifyBufferCollectionToken(),而不是在 IsAlternateFor() 因调用令牌不是真实令牌(并非真正与 sysmem 通信)而一直未响应的情况下,调用 VerifyBufferCollectionToken(),而不是无限期地陷入困境。另一种方法是先使用此令牌调用 BindSharedCollection,该令牌也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示未在与调用节点相同的逻辑缓冲区集合中找到 node_ref。在逻辑分配之前以及同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 至少会一直存在,直到逻辑分配(包括已完成 Close() 和关闭其通道的节点)才继续存在,并且如果 ZX_ERR_NOT_FOUND 尚未返回逻辑分配,则此节点不会返回。在逻辑分配之后或在其他逻辑分配子树中,还有其他可能造成此错误的原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此 Node 逻辑分配分隔)可能会导致其子树失效而删除这些节点,或者可能存在 BufferCollectionTokenGroup 存在,并且可能会选择与 node_ref 所在的子树不同的子树,从而导致 Node_ref 被删除。仅当系统使用 Close() 且节点的子树尚未失败时,系统才会在节点没有相应的通道之后保留该节点。出现此错误的另一个原因是,node_ref 是具有足够权限的事件对句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是事件对句柄,或者没有在实际 node_ref 上预期的权限。
此调用不会返回其他失败的状态代码。不过,sysmem 将来可能会添加其他代码,以便客户端应对所有失败的状态代码进行合理的默认处理。
成功后,is_alternate 具有以下含义:
- true - 调用节点与 node_ref 节点之间的第一个父节点是 BufferCollectionTokenGroup。这意味着,调用的 Node 和 node_ref 节点不会同时应用其这两项约束条件,而是 sysmem 会选择其中一个约束条件,但绝不会同时应用两者。这是因为在逻辑分配期间只会选择 BufferCollectionTokenGroup 的一个子项,并且只有该子项的子树对约束聚合有贡献。
- false - 调用节点和 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同的父节点是 BufferCollectionToken 或 BufferCollection(无论是否为 Close()ed 或 Close()ed)。这意味着,如果任何涉及的父 BufferCollectionTokenGroup 同时选择了这两个节点,则调用节点和 node_ref 节点可以在逻辑分配的约束聚合期间应用它们的约束条件。在这种情况下,没有 BufferCollectionTokenGroup 可直接阻止选择两个节点及其约束条件进行汇总,但即使值为 false,如果一个或两个 Node 具有直接或间接父 BufferCollectionTokenGroup,且该子树选择除调用 Node 或
请求
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
响应
名称 | 类型 |
---|---|
payload |
Node_IsAlternateFor_Result
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可以使用这些信息来调试泄漏内存并挂起等待约束。|name| 可以是任意字符串,但最好使用当前进程名称(请参阅 fsl::GetCurrentProcessName())。|id| 可以是任意 ID,但最好使用当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())。
在启用详细日志记录功能时,也会使用该选项(请参阅 SetVerboseLogging()),以指明哪个客户端首先关闭其通道,进而导致子树故障(如果子树的用途结束,这可能是正常的,但如果发生的时间早于预期,客户端渠道专用名称有助于从 sysmem 的角度诊断故障首先来自何处)。
默认情况下(除非被此消息或使用 Allocator.SetDebugClientInfo() 替换),否则节点会在创建子节点时从其父节点复制信息。虽然这样做总比什么都好,但每个参与者通常最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 将信息与当前客户端直接相关。此外,SetVerboseLogging() 可用于帮助消除歧义,确定某个节点是否涉嫌包含从其父节点复制的信息。
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制条件,Ssmem 就会记录一条警告。客户端可以调用此方法来在输出日志时进行更改。如果由多个客户端设置了截止期限,则未指定截止期限的生效时间。
请求
名称 | 类型 |
---|---|
deadline |
zx/Time
|
SetDispensable
在对缓冲区进行逻辑分配后,可分配令牌可能会失败,而不会导致其父令牌(如果有)失败。
在逻辑缓冲区分配之前,可分配令牌会与其父级一起参与约束汇总。如果可分配令牌在进行逻辑分配缓冲区之前失败,则失败会传播到可分配令牌的父级。
在对缓冲区进行逻辑分配之后,可分配令牌(或可分配令牌的任何子项)的失败不会传播到可分配令牌的父级。失败会从可分配令牌的常规子节点传播到可分配令牌。如果附加了子项,或者子项可分配且在逻辑分配之后发生故障,则子项故障将无法到达其父项。
在参与者需要提供约束条件的情况下,可以使用可分发令牌,但在分配缓冲区后,参与者可以失败,而不会从父人的角度导致缓冲区收集失败。
相比之下,AttachToken() 可用于创建一个令牌,该令牌不与其父级参与约束汇总,在任意时间失败不会传播到其父级,并且其提供约束的延迟不会阻止父级完成其缓冲区分配。
在某些情况下,发起者可能会选择最初为参与者的给定实例使用可分配令牌,之后如果该参与者的第一个实例失败,该参与者的第二个实例将获得使用 AttachToken() 创建的令牌。
如果客户端使用此消息,则由于客户端具有 SetDispensable() 且已提供给其他进程的任何 BufferCollectionToken 或 BufferCollection 突然失败,客户端不应依赖客户端自己的 BufferCollectionToken 或 BufferCollection 通道从服务器端关闭。因此,客户端应格外小心,通过其他方式发现其他进程失败。
虽然可以在 BufferCollectionTokenGroup 的直接子项上使用 SetDispensable(),但稍后无法使用 AttachToken() 用新令牌替换失败的可分发令牌(因为组上没有 AttachToken())。在这种情况下,要启用 AttachToken() 替换,请另外创建一个不可分发令牌(节点)作为该组的直接子项,并将现有的可分配令牌设为附加令牌(节点)的子项。这样,作为该组的直接子项的额外令牌(节点)具有 BufferCollection.AttachToken(),可用于替换失败的可分配令牌。
对已经分发的令牌进行的 SetDispensable() 具有幂等性。
请求
<EMPTY>
SetName
设置此缓冲区集合中的 VMO 的名称。此名称可能会被截短。该名称只会影响在设置后分配的虚拟机 OS,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值越大,优先级越高。
请求
名称 | 类型 |
---|---|
priority |
uint32
|
name |
string[64]
|
SetVerboseLogging
详细日志记录功能包括从每个客户端通过 SetConstraints() 设置的约束、通过 SetDebugClientInfo() 设置的信息,以及节点树的结构。
通常,当汇总失败时,sysmem 仅输出一行投诉,并且仅会显示汇总失败的具体详细原因,并提供最少的上下文。虽然这通常足以诊断出问题(如果仅进行了细微更改,并且系统在小更改之前就已正常运行),但对于首次获取新的缓冲区集合来说,这通常不是特别有帮助。尤其是对于涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树,详细日志记录有助于诊断树的外观及其逻辑分配失败的原因,或者树或子树的失败速度比预期更快的原因。
如果仅在少量缓冲区集合中启用额外日志记录,那么从性能的角度来看,额外日志记录是可以接受的。如果我们没有追踪错误,则不应发送此邮件。
如果太多参与者将详细日志记录功能保持启用状态,我们最终可能需要要求通过一些其他设置允许系统级系统内存详细日志记录功能,以避免系统因此消息而过多地向日志发送垃圾内容。
如果我们对某个节点的信任不够充分,无法允许其启用详细日志记录功能,则由于与节点关联的有意政策,这对某些节点而言可能是一个 NOP。
请求
<EMPTY>
同步
确保已在服务器端收到之前的消息,包括令牌、集合或组上的 Duplicate() 消息。
对无效/无效的 sysmem 令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永久挂起。若要以一次往返为代价来降低恶意/虚假 BufferCollectionToken 的可能性,请参阅 VerifyBufferCollectionToken()。另一种方法是将令牌传递给 BindSharedCollection(),后者还会在将令牌交换为 BufferCollection 通道时验证令牌,然后可以使用 BufferCollection Sync()。
在 Sync() 之后,您可以放心地将 token_request 的客户端端发送给其他参与者,并知道在另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括等待每个 token.Duplicate() 完成(在每个令牌之后单独调用 token.Sync()),或者在通过 BindSharedCollection() 上交令牌后在 BufferCollection 上调用 Sync()。
另一种缓解措施是避免对令牌调用 Sync(),改为在原始令牌无效时处理 BufferCollection.Sync() 可能失败的问题。从性能的角度来看,这是更可取的方法,但要求客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将重复令牌转换为 BufferCollection 并从 BufferCollection.Sync() 收到成功响应之后。
在可行的情况下,最好改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,调用方必须已经知道此令牌有效/有效,否则 BufferCollectionToken.Sync() 可能会永久挂起。如果还不知道令牌是否有效,请先查看 RestrictBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
BufferCollectionTokenGroup
在 fuchsia.sysmem/collection.fidl 中定义
系统实现可以保证与逻辑/概念模型保持一致,如下所示:
通常,逻辑分配会考虑根和与根没有传递 AttachToken() 相连的节点的所有节点,或者以 AttachToken() 令牌为根的子树,以及与该子树建立连接且不转换其他 AttachToken() 的所有节点。这称为逻辑分配剪除的子树,或简称为剪除的子树。
在约束条件聚合期间,每个 BufferCollectionTokenGroup 将在其子项中选择一个子令牌。其余子项似乎未通过逻辑分配,而所选子项可能会成功。
当在整体逻辑分配剪除的子树中存在多个 BufferCollectionTokenGroup 时,两个组之间的相对优先级等同于其在树的 DFS 预订迭代中的顺序,其中父项的优先级高于子项,左侧子项的优先级高于右侧子项。
选择某个组的特定子项(无论是在约束汇总尝试期间临时选择,还是作为最终选择)时,如果未选择该组的其他子项,则可能会在这些未选择的子项下“隐藏”其他组。
在逻辑分配中,首先尝试通过以下方式进行汇总:临时选择优先级最高的组的子项 0,以及尚未被临时选择目前隐藏的下一个最高优先级组的子项 0,等等。
如果该汇总尝试失败,系统将尝试对所有相同组的序数 0 子组进行汇总,但优先级最低的非隐藏组将暂时选择其序数 1 个子组(然后选择子组 2,依此类推)。如果更新优先级最低的新组时已取消隐藏,在更改之前优先级最低的组中的临时选择之前,新取消隐藏的最低优先级组会按顺序考虑其所有子组。就结果而言,这相当于按照计数类顺序对所有可能的选项组合进行系统枚举,以最高频率更新优先级最低的群组,以最低频率更新优先级最高的群组。我们可以跳过由于隐藏而不对结果进行任何更改而冗余/等效的组合,而不是实际尝试使用所有组合进行汇总。
系统会以这种方式继续尝试对枚举的非等效选项组合进行聚合,直到 (a) 所有汇总尝试失败(在这种情况下整体逻辑分配失败)或 (b) 直到尝试聚合成功(在这种情况下,系统会尝试一次缓冲区分配(如果需要))。如果基于第一次成功汇总的缓冲区分配失败,则整体逻辑分配失败(没有缓冲区分配重试 / 重试)。如果缓冲区分配成功(或不需要),逻辑分配也会成功。
如果此优先级方案无法满足您对 Sysmem 的使用需求,请与 Sysmem 相关人员联系,商讨添加方法来实现您所需的可能。
请避免为每个逻辑分配创建大量的 BufferCollectionTokenGroup,尤其是对于总共大量的子项,尤其是在以下情况下:使用序数 0 的子项(可能也会使用序数 0 的子项)会导致汇总操作失败。我们预计,通过在考虑的组子组合/选择数量上限(相当高但并不庞大)超出某个上限(相当高但并不庞大)的情况下,在过多组中评估过多子组合/选择时可能较高的时间复杂性降低。更高级(且更复杂的)缓解措施预计没有实际必要,也不值得增加复杂性。如果达到上限或您预计会达到上限,请与系统相关人员联系,讨论可能的方案。
如果可行,最好在单个 BufferCollectionConstraints 中使用多个 ImageFormatConstraints(当参与者只需要表达可以使用多种 PixelFormat 的能力时,由系统在所有参与者支持的那些格式中选择要使用哪种 PixelFormat)。
与 BufferCollectionToken 和 BufferCollection 类似,在不先发送 Close() 的情况下关闭 BufferCollectionTokenGroup 通道将会导致逻辑缓冲区收集失败(如果使用 SetDispensable() 或 AttachToken() 并且 BufferCollectionTokenGroup 是此类节点下不会将故障传播到其父级的子树的一部分,则会导致子树故障)。
AllChildrenPresent
AllChildrenPresent()
创建所有子级后,客户端必须调用 AllChildrenPresent() 来告知 sysmem 不会再创建任何子级,以便 sysmem 可以知道何时可以开始聚合限制条件。
如果要发送 Close(),它应该在 AllChildrenPresent() 之后发送,否则仍然会触发组失败,并且仍会将失败事件传播到组的父级。
请求
<EMPTY>
关闭
在 BufferCollectionToken 通道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地关闭该令牌(然后立即或稍后关闭该通道,以响应服务器关闭其端),从而避免逻辑缓冲区收集失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,服务器通过使整个逻辑缓冲区收集失败来处理 BufferCollection 的意外故障。部分原因在于在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者想要彻底关闭 BufferCollection 视图,而不会导致逻辑缓冲区收集失败,则可以在关闭 BufferCollection 通道的客户端端之前发送 Close()。如果这是最后一个 BufferCollection 视图,逻辑缓冲区收集仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前,则缓冲区集合将不需要此节点的约束来分配。如果在 SetConstraints() 之后,约束条件将保留并连同任何后续逻辑分配一起聚合,尽管缺少通道连接。
在 BufferCollectionTokenGroup 通道上:
默认情况下,BufferCollectionTokenGroup 出现意外故障将触发逻辑 BufferCollectionTokenGroup 故障,并将故障传播至其父级。若要关闭 BufferCollectionTokenGroup 通道而不使逻辑组失败或传播故障,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,那么即使发生 Close(),逻辑缓冲区收集仍会失败(因为系统管理器无法确定是否创建了所有相关的子项,因此是否将所有相关约束条件都提供给系统尚不清楚)。如果 Close() 发生在 AllChildrenPresent() 之后,则子节点及其所有约束条件都会保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态时一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
CreateChild
创建子令牌。在将此令牌的客户端端传递给 BindSharedCollection()之前,必须在 CreateChild() 之后完成 Sync()。或者,客户端可以使用 CreateChildrenSync(),实质上包含 Sync()。
token_request - 新令牌通道的服务器端。
Rights_attenuation_mask - 如果为 ZX_RIGHT_SAME_RIGHTS,则创建的令牌允许持有人获取缓冲区(与(群组)的父令牌拥有的相同权限)的权限。
请求
名称 | 类型 |
---|---|
payload |
BufferCollectionTokenGroupCreateChildRequest
|
CreateChildrenSync
同步创建 1 个或多个子令牌。与 CreateChild() 相比,在将返回令牌的客户端端传递给 BindSharedCollection(),之前无需 Sync() 完成。
Rights_attentuation_mask 的大小决定了创建的子令牌的数量。
索引较低子令牌的优先级高于(尝试较快)的子令牌。
根据所有子令牌,成功聚合将从所有已创建的子项(在可能多次调用 CreateChild() 和 CreateChildrenSync() 中创建的所有子项中)仅选择一个子项。
每个组允许的子项总数上限以及整个树中的节点总数(从根开始)均受限于无法通过这些协议配置的限制。
请求
名称 | 类型 |
---|---|
rights_attenuation_masks |
vector<zx/Rights>[64]
|
响应
名称 | 类型 |
---|---|
tokens |
vector<BufferCollectionToken>[64]
|
GetNodeRef
这将获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端将无权发出此事件,因为此句柄只能用作客户端从此节点获取此句柄的证明。
由于这是一个 get 而非 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能位于不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
IsAlternateFor
这将检查调用节点是否位于某个子树中,该子树的根位置为与传入 node_ref 相关的共同父 BufferCollectionTokenGroup 的不同子令牌。
此调用旨在协助准入控制去重和调试。
必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取 node_ref。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时调用 GetNodeRef()。
如果由于调用令牌的提供者可能存在恶意/不可信,导致调用令牌实际上可能根本不是有效令牌,请先调用 VerifyBufferCollectionToken(),而不是在 IsAlternateFor() 因调用令牌不是真实令牌(并非真正与 sysmem 通信)而一直未响应的情况下,调用 VerifyBufferCollectionToken(),而不是无限期地陷入困境。另一种方法是先使用此令牌调用 BindSharedCollection,该令牌也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示未在与调用节点相同的逻辑缓冲区集合中找到 node_ref。在逻辑分配之前以及同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 至少会一直存在,直到逻辑分配(包括已完成 Close() 和关闭其通道的节点)才继续存在,并且如果 ZX_ERR_NOT_FOUND 尚未返回逻辑分配,则此节点不会返回。在逻辑分配之后或在其他逻辑分配子树中,还有其他可能造成此错误的原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此 Node 逻辑分配分隔)可能会导致其子树失效而删除这些节点,或者可能存在 BufferCollectionTokenGroup 存在,并且可能会选择与 node_ref 所在的子树不同的子树,从而导致 Node_ref 被删除。仅当系统使用 Close() 且节点的子树尚未失败时,系统才会在节点没有相应的通道之后保留该节点。出现此错误的另一个原因是,node_ref 是具有足够权限的事件对句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是事件对句柄,或者没有在实际 node_ref 上预期的权限。
此调用不会返回其他失败的状态代码。不过,sysmem 将来可能会添加其他代码,以便客户端应对所有失败的状态代码进行合理的默认处理。
成功后,is_alternate 具有以下含义:
- true - 调用节点与 node_ref 节点之间的第一个父节点是 BufferCollectionTokenGroup。这意味着,调用的 Node 和 node_ref 节点不会同时应用其这两项约束条件,而是 sysmem 会选择其中一个约束条件,但绝不会同时应用两者。这是因为在逻辑分配期间只会选择 BufferCollectionTokenGroup 的一个子项,并且只有该子项的子树对约束聚合有贡献。
- false - 调用节点和 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同的父节点是 BufferCollectionToken 或 BufferCollection(无论是否为 Close()ed 或 Close()ed)。这意味着,如果任何涉及的父 BufferCollectionTokenGroup 同时选择了这两个节点,则调用节点和 node_ref 节点可以在逻辑分配的约束聚合期间应用它们的约束条件。在这种情况下,没有 BufferCollectionTokenGroup 可直接阻止选择两个节点及其约束条件进行汇总,但即使值为 false,如果一个或两个 Node 具有直接或间接父 BufferCollectionTokenGroup,且该子树选择除调用 Node 或
请求
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
响应
名称 | 类型 |
---|---|
payload |
Node_IsAlternateFor_Result
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可以使用这些信息来调试泄漏内存并挂起等待约束。|name| 可以是任意字符串,但最好使用当前进程名称(请参阅 fsl::GetCurrentProcessName())。|id| 可以是任意 ID,但最好使用当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())。
在启用详细日志记录功能时,也会使用该选项(请参阅 SetVerboseLogging()),以指明哪个客户端首先关闭其通道,进而导致子树故障(如果子树的用途结束,这可能是正常的,但如果发生的时间早于预期,客户端渠道专用名称有助于从 sysmem 的角度诊断故障首先来自何处)。
默认情况下(除非被此消息或使用 Allocator.SetDebugClientInfo() 替换),否则节点会在创建子节点时从其父节点复制信息。虽然这样做总比什么都好,但每个参与者通常最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 将信息与当前客户端直接相关。此外,SetVerboseLogging() 可用于帮助消除歧义,确定某个节点是否涉嫌包含从其父节点复制的信息。
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制条件,Ssmem 就会记录一条警告。客户端可以调用此方法来在输出日志时进行更改。如果由多个客户端设置了截止期限,则未指定截止期限的生效时间。
请求
名称 | 类型 |
---|---|
deadline |
zx/Time
|
SetName
设置此缓冲区集合中的 VMO 的名称。此名称可能会被截短。该名称只会影响在设置后分配的虚拟机 OS,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值越大,优先级越高。
请求
名称 | 类型 |
---|---|
priority |
uint32
|
name |
string[64]
|
SetVerboseLogging
详细日志记录功能包括从每个客户端通过 SetConstraints() 设置的约束、通过 SetDebugClientInfo() 设置的信息,以及节点树的结构。
通常,当汇总失败时,sysmem 仅输出一行投诉,并且仅会显示汇总失败的具体详细原因,并提供最少的上下文。虽然这通常足以诊断出问题(如果仅进行了细微更改,并且系统在小更改之前就已正常运行),但对于首次获取新的缓冲区集合来说,这通常不是特别有帮助。尤其是对于涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树,详细日志记录有助于诊断树的外观及其逻辑分配失败的原因,或者树或子树的失败速度比预期更快的原因。
如果仅在少量缓冲区集合中启用额外日志记录,那么从性能的角度来看,额外日志记录是可以接受的。如果我们没有追踪错误,则不应发送此邮件。
如果太多参与者将详细日志记录功能保持启用状态,我们最终可能需要要求通过一些其他设置允许系统级系统内存详细日志记录功能,以避免系统因此消息而过多地向日志发送垃圾内容。
如果我们对某个节点的信任不够充分,无法允许其启用详细日志记录功能,则由于与节点关联的有意政策,这对某些节点而言可能是一个 NOP。
请求
<EMPTY>
同步
确保已在服务器端收到之前的消息,包括令牌、集合或组上的 Duplicate() 消息。
对无效/无效的 sysmem 令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永久挂起。若要以一次往返为代价来降低恶意/虚假 BufferCollectionToken 的可能性,请参阅 VerifyBufferCollectionToken()。另一种方法是将令牌传递给 BindSharedCollection(),后者还会在将令牌交换为 BufferCollection 通道时验证令牌,然后可以使用 BufferCollection Sync()。
在 Sync() 之后,您可以放心地将 token_request 的客户端端发送给其他参与者,并知道在另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括等待每个 token.Duplicate() 完成(在每个令牌之后单独调用 token.Sync()),或者在通过 BindSharedCollection() 上交令牌后在 BufferCollection 上调用 Sync()。
另一种缓解措施是避免对令牌调用 Sync(),改为在原始令牌无效时处理 BufferCollection.Sync() 可能失败的问题。从性能的角度来看,这是更可取的方法,但要求客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将重复令牌转换为 BufferCollection 并从 BufferCollection.Sync() 收到成功响应之后。
在可行的情况下,最好改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,调用方必须已经知道此令牌有效/有效,否则 BufferCollectionToken.Sync() 可能会永久挂起。如果还不知道令牌是否有效,请先查看 RestrictBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
DriverConnector
在 fuchsia.sysmem/driver_connector.fidl 中定义
向驱动程序建立具有此接口的通道后(通常处于提前状态),此接口便允许将由驱动程序提供的分配器通道的服务器端异步发送。
目前,由 sysmem 驱动程序通过常规 devhost FIDL 调度代码直接提供的 FIDL 接口是该接口。其他系统接口由单独的调度代码提供,这主要是因为我们希望能够通过向驱动程序发送服务器通道来建立异步通道,而无需打开往返过程,也无需将该通道作为文件描述符进行管理。
https://fxbug.dev/42108063 跟踪的当前次要原因是当前的 devhost 调度代码不允许异步处理请求,我们希望至少为了 BufferCollection 接口的正常运行,因为该接口有一些请求在 devhost 受到其他参与者的限制之前完成。
连接
此单向消息在分配器通道的服务器端发送。
allocator_request
将由 sysmem 驱动程序提供(或者该通道将关闭)。
请求
名称 | 类型 |
---|---|
allocator_request |
server_end<Allocator>
|
SetAuxServiceDirectory
请求
名称 | 类型 |
---|---|
service_directory |
fuchsia.io/Directory
|
节点
在 fuchsia.sysmem/collection.fidl 中定义
关闭
在 BufferCollectionToken 通道上:
通常,参与者会将 BufferCollectionToken 转换为 BufferCollection 视图,但参与者也可以自由地关闭该令牌(然后立即或稍后关闭该通道,以响应服务器关闭其端),从而避免逻辑缓冲区收集失败。通常,意外的令牌通道关闭会导致逻辑缓冲区收集失败(唯一的例外情况是涉及 AttachToken() 或 SetDispensable() 的某些情况)。
在 BufferCollection 通道上:
默认情况下,服务器通过使整个逻辑缓冲区收集失败来处理 BufferCollection 的意外故障。部分原因在于在任何参与者失败时加快关闭 VMO 句柄以回收内存。如果参与者想要彻底关闭 BufferCollection 视图,而不会导致逻辑缓冲区收集失败,则可以在关闭 BufferCollection 通道的客户端端之前发送 Close()。如果这是最后一个 BufferCollection 视图,逻辑缓冲区收集仍会消失。Close() 可以在 SetConstraints() 之前或之后发生。如果在 SetConstraints() 之前,则缓冲区集合将不需要此节点的约束来分配。如果在 SetConstraints() 之后,约束条件将保留并连同任何后续逻辑分配一起聚合,尽管缺少通道连接。
在 BufferCollectionTokenGroup 通道上:
默认情况下,BufferCollectionTokenGroup 出现意外故障将触发逻辑 BufferCollectionTokenGroup 故障,并将故障传播至其父级。若要关闭 BufferCollectionTokenGroup 通道而不使逻辑组失败或传播故障,请在关闭通道客户端端点之前发送 Close()。
如果 Close() 发生在 AllChildrenPresent() 之前,那么即使发生 Close(),逻辑缓冲区收集仍会失败(因为系统管理器无法确定是否创建了所有相关的子项,因此是否将所有相关约束条件都提供给系统尚不清楚)。如果 Close() 发生在 AllChildrenPresent() 之后,则子节点及其所有约束条件都会保持不变(就像 BufferCollectionTokenGroup 通道保持打开状态时一样),并且关闭不会触发或传播失败。
请求
<EMPTY>
GetNodeRef
这将获取一个事件句柄,该句柄可用作在任何节点上调用的 IsAlternateFor() 的参数。客户端将无权发出此事件,因为此句柄只能用作客户端从此节点获取此句柄的证明。
由于这是一个 get 而非 set,因此在 GetNodeRef() 和对 IsAlternateFor() 的调用之间不需要 Sync(),尽管这两个调用可能位于不同的通道上。
另请参阅 IsAlternateFor()。
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
IsAlternateFor
这将检查调用节点是否位于某个子树中,该子树的根位置为与传入 node_ref 相关的共同父 BufferCollectionTokenGroup 的不同子令牌。
此调用旨在协助准入控制去重和调试。
必须使用 BufferCollectionToken、BufferCollection 或 BufferCollectionTokenGroup 的 GetNodeRef() 获取 node_ref。
node_ref 可以是重复的句柄;无需在每次调用 IsAlternateFor() 时调用 GetNodeRef()。
如果由于调用令牌的提供者可能存在恶意/不可信,导致调用令牌实际上可能根本不是有效令牌,请先调用 VerifyBufferCollectionToken(),而不是在 IsAlternateFor() 因调用令牌不是真实令牌(并非真正与 sysmem 通信)而一直未响应的情况下,调用 VerifyBufferCollectionToken(),而不是无限期地陷入困境。另一种方法是先使用此令牌调用 BindSharedCollection,该令牌也会验证令牌并将其转换为 BufferCollection,然后调用 BufferCollection IsAlternateFor()。
错误值:
ZX_ERR_NOT_FOUND 表示未在与调用节点相同的逻辑缓冲区集合中找到 node_ref。在逻辑分配之前以及同一逻辑分配子树中,这实质上意味着 node_ref 从未属于此逻辑缓冲区集合,因为在逻辑分配之前,所有存在的 node_ref 至少会一直存在,直到逻辑分配(包括已完成 Close() 和关闭其通道的节点)才继续存在,并且如果 ZX_ERR_NOT_FOUND 尚未返回逻辑分配,则此节点不会返回。在逻辑分配之后或在其他逻辑分配子树中,还有其他可能造成此错误的原因。例如,不同的逻辑分配(通过 AttachToken() 或 SetDispensable() 与此 Node 逻辑分配分隔)可能会导致其子树失效而删除这些节点,或者可能存在 BufferCollectionTokenGroup 存在,并且可能会选择与 node_ref 所在的子树不同的子树,从而导致 Node_ref 被删除。仅当系统使用 Close() 且节点的子树尚未失败时,系统才会在节点没有相应的通道之后保留该节点。出现此错误的另一个原因是,node_ref 是具有足够权限的事件对句柄,但实际上并不是从 GetNodeRef() 获取的真实 node_ref。
ZX_ERR_INVALID_ARGS 表示调用方传递的 node_ref 不是事件对句柄,或者没有在实际 node_ref 上预期的权限。
此调用不会返回其他失败的状态代码。不过,sysmem 将来可能会添加其他代码,以便客户端应对所有失败的状态代码进行合理的默认处理。
成功后,is_alternate 具有以下含义:
- true - 调用节点与 node_ref 节点之间的第一个父节点是 BufferCollectionTokenGroup。这意味着,调用的 Node 和 node_ref 节点不会同时应用其这两项约束条件,而是 sysmem 会选择其中一个约束条件,但绝不会同时应用两者。这是因为在逻辑分配期间只会选择 BufferCollectionTokenGroup 的一个子项,并且只有该子项的子树对约束聚合有贡献。
- false - 调用节点和 node_ref 节点之间的第一个共同父节点不是 BufferCollectionTokenGroup。目前,这意味着第一个共同的父节点是 BufferCollectionToken 或 BufferCollection(无论是否为 Close()ed 或 Close()ed)。这意味着,如果任何涉及的父 BufferCollectionTokenGroup 同时选择了这两个节点,则调用节点和 node_ref 节点可以在逻辑分配的约束聚合期间应用它们的约束条件。在这种情况下,没有 BufferCollectionTokenGroup 可直接阻止选择两个节点及其约束条件进行汇总,但即使值为 false,如果一个或两个 Node 具有直接或间接父 BufferCollectionTokenGroup,且该子树选择除调用 Node 或
请求
名称 | 类型 |
---|---|
node_ref |
handle<event>
|
响应
名称 | 类型 |
---|---|
payload |
Node_IsAlternateFor_Result
|
SetDebugClientInfo
设置有关当前客户端的信息,sysmem 可以使用这些信息来调试泄漏内存并挂起等待约束。|name| 可以是任意字符串,但最好使用当前进程名称(请参阅 fsl::GetCurrentProcessName())。|id| 可以是任意 ID,但最好使用当前进程 ID(请参阅 fsl::GetCurrentProcessKoid())。
在启用详细日志记录功能时,也会使用该选项(请参阅 SetVerboseLogging()),以指明哪个客户端首先关闭其通道,进而导致子树故障(如果子树的用途结束,这可能是正常的,但如果发生的时间早于预期,客户端渠道专用名称有助于从 sysmem 的角度诊断故障首先来自何处)。
默认情况下(除非被此消息或使用 Allocator.SetDebugClientInfo() 替换),否则节点会在创建子节点时从其父节点复制信息。虽然这样做总比什么都好,但每个参与者通常最好使用 Node.SetDebugClientInfo() 或 Allocator.SetDebugClientInfo() 将信息与当前客户端直接相关。此外,SetVerboseLogging() 可用于帮助消除歧义,确定某个节点是否涉嫌包含从其父节点复制的信息。
请求
名称 | 类型 |
---|---|
name |
string[64]
|
id |
uint64
|
SetDebugTimeoutLogDeadline
如果并非所有客户端都在创建集合 5 秒后设置了限制条件,Ssmem 就会记录一条警告。客户端可以调用此方法来在输出日志时进行更改。如果由多个客户端设置了截止期限,则未指定截止期限的生效时间。
请求
名称 | 类型 |
---|---|
deadline |
zx/Time
|
SetName
设置此缓冲区集合中的 VMO 的名称。此名称可能会被截短。该名称只会影响在设置后分配的虚拟机 OS,此调用不会重命名现有 VMO。如果多个客户端设置了不同的名称,则优先级值越大,优先级越高。
请求
名称 | 类型 |
---|---|
priority |
uint32
|
name |
string[64]
|
SetVerboseLogging
详细日志记录功能包括从每个客户端通过 SetConstraints() 设置的约束、通过 SetDebugClientInfo() 设置的信息,以及节点树的结构。
通常,当汇总失败时,sysmem 仅输出一行投诉,并且仅会显示汇总失败的具体详细原因,并提供最少的上下文。虽然这通常足以诊断出问题(如果仅进行了细微更改,并且系统在小更改之前就已正常运行),但对于首次获取新的缓冲区集合来说,这通常不是特别有帮助。尤其是对于涉及 AttachToken()、SetDispensable()、BufferCollectionTokenGroup 节点和关联的节点子树等更复杂的节点树,详细日志记录有助于诊断树的外观及其逻辑分配失败的原因,或者树或子树的失败速度比预期更快的原因。
如果仅在少量缓冲区集合中启用额外日志记录,那么从性能的角度来看,额外日志记录是可以接受的。如果我们没有追踪错误,则不应发送此邮件。
如果太多参与者将详细日志记录功能保持启用状态,我们最终可能需要要求通过一些其他设置允许系统级系统内存详细日志记录功能,以避免系统因此消息而过多地向日志发送垃圾内容。
如果我们对某个节点的信任不够充分,无法允许其启用详细日志记录功能,则由于与节点关联的有意政策,这对某些节点而言可能是一个 NOP。
请求
<EMPTY>
同步
确保已在服务器端收到之前的消息,包括令牌、集合或组上的 Duplicate() 消息。
对无效/无效的 sysmem 令牌调用 BufferCollectionToken.Sync() 可能会导致 Sync() 永久挂起。若要以一次往返为代价来降低恶意/虚假 BufferCollectionToken 的可能性,请参阅 VerifyBufferCollectionToken()。另一种方法是将令牌传递给 BindSharedCollection(),后者还会在将令牌交换为 BufferCollection 通道时验证令牌,然后可以使用 BufferCollection Sync()。
在 Sync() 之后,您可以放心地将 token_request 的客户端端发送给其他参与者,并知道在另一个参与者将令牌发送到 BindSharedCollection() 时,服务器会识别该令牌。
其他选项包括等待每个 token.Duplicate() 完成(在每个令牌之后单独调用 token.Sync()),或者在通过 BindSharedCollection() 上交令牌后在 BufferCollection 上调用 Sync()。
另一种缓解措施是避免对令牌调用 Sync(),改为在原始令牌无效时处理 BufferCollection.Sync() 可能失败的问题。从性能的角度来看,这是更可取的方法,但要求客户端代码延迟发送从此令牌复制的令牌,直到客户端代码将重复令牌转换为 BufferCollection 并从 BufferCollection.Sync() 收到成功响应之后。
在可行的情况下,最好改用 BufferCollection.Sync()(见上文)。 如果 BufferCollection.Sync() 不可行,调用方必须已经知道此令牌有效/有效,否则 BufferCollectionToken.Sync() 可能会永久挂起。如果还不知道令牌是否有效,请先查看 RestrictBufferCollectionToken() 以检查令牌有效性。
请求
<EMPTY>
响应
<EMPTY>
SecureMem
在 fuchsia.sysmem/secure_mem.fidl 中定义
SecureMem
客户端是 sysmem。服务器是 safemem 驱动程序。
TEE - 可信执行环境。
REE - 丰富的执行环境。
使 sysmem 能够调用 safemem 驱动程序,以获取通过 TEE(或通过 safemem 驱动程序)配置的任何安全堆,并设置通过 sysmem 配置的所有物理安全堆。
目前,动态分配的安全堆是通过 sysmem 配置的,因为它在启动期间很早就启动,可以成功预留连续的物理内存。目前,固定位置的安全堆通过 TEE 进行配置,因为连接从引导加载程序前往 TEE。不过,此协议有意忽略哪些堆是动态分配的,哪些堆是固定的。
AddSecureHeapPhysicalRange
这个从 sysmem 到 safemem 驱动程序的请求传达了要添加的物理范围,因为堆的物理范围是通过 sysmem 设置的。
只有 sysmem 可以调用此属性,因为只有 sysmem 会通过 RegisterSecureMem() 将提供此协议的 FIDL 通道的客户端端交给 RegisterSecureMem()。securemem 驱动程序是此协议的服务器端。
Securemem 驱动程序必须将所有涵盖的偏移量配置为受保护,然后才能成功响应此消息。
失败时,safemem 驱动程序必须确保未创建受保护的范围。
如果 dynamic_protection_ranges 为 false,系统则只能调用一次此选项。
如果 dynamic_protection_ranges 为 true,则只要当前范围数量不超过 max_protected_range_count,sysmem 就可以多次调用此属性。
调用方不得尝试添加与现有范围匹配的范围。只要两个范围都不完全匹配,添加的范围可以相互重叠。
错误数:
- ZX_ERR_BAD_STATE - 在 !dynamic_protection_ranges. 添加会导致总堆计数超过 max_protected_range_count 的堆。
- ZX_ERR_INVALID_ARGS - 意外的堆或不符合 Protect_range_granularity 要求的范围。
- ZX_ERR_INTERNAL - 常规内部错误(例如与 TEE 通信时不会生成 zx_status_t 错误)。
- 其他错误,例如由于通信失败或服务器传播 zx_status_t 故障。
请求
名称 | 类型 |
---|---|
heap_range |
SecureHeapAndRange
|
响应
名称 | 类型 |
---|---|
payload |
SecureMem_AddSecureHeapPhysicalRange_Result
|
DeleteSecureHeapPhysicalRange
这个从 sysmem 到 safemem 驱动程序的请求传达了待删除的物理范围,适用于通过 sysmem 设置的物理范围。
只有 sysmem 可以调用此属性,因为只有 sysmem 会通过 RegisterSecureMem() 将提供此协议的 FIDL 通道的客户端端交给 RegisterSecureMem()。securemem 驱动程序是此协议的服务器端。
Securemem 驱动程序必须先将所有涵盖的偏移量配置为不受保护,然后才能成功响应此消息。
失败时,securemem 驱动程序必须确保受保护的范围不会被删除。
如果 dynamic_protection_ranges 为 false,系统则不得调用此方法。
如果 dynamic_protection_ranges 为 true,则 sysmem 可以在调用时存在的各种范围内重复调用此属性。
如果所删除范围的任何部分也未包含在另一个受保护的范围中,那么整个范围中任何部分正在进行的任何 DMA 都可能会中断 / 失败,从而可能会破坏整个系统(总线锁定或类似情况,具体取决于设备详细信息)。因此,调用方必须确保要删除的范围中的任何部分都不会发生正在进行的 DMA,除非调用方有其他活跃范围覆盖了要删除的范围中的每个块。正在删除的 DMA 与要删除的范围之外的数据块之间的持续性 DMA 永远不会受到删除操作的影响。
错误数:
- ZX_ERR_BAD_STATE - 在 !dynamic_protection_ranges 时调用。
- ZX_ERR_INVALID_ARGS - 意外的堆或不符合 Protect_range_granularity 要求的范围。
- ZX_ERR_INTERNAL - 常规内部错误(例如与 TEE 通信时不会生成 zx_status_t 错误)。
- ZX_ERR_NOT_FOUND - 未找到指定的范围。
- 其他错误,例如由于通信失败或服务器传播 zx_status_t 故障。
请求
名称 | 类型 |
---|---|
heap_range |
SecureHeapAndRange
|
响应
名称 | 类型 |
---|---|
payload |
SecureMem_DeleteSecureHeapPhysicalRange_Result
|
GetPhysicalSecureHeapProperties
这个从 sysmem 到 safemem 驱动程序的请求会获取受保护/安全堆的属性。
此方法只能处理具有单个连续物理范围的堆。
如果此请求需要一些物理空间来自动检测有多少个 REE 可用范围,则会指示堆的整个物理范围。在此请求完成之前,所有临时硬件保护范围都将被删除。
请求
名称 | 类型 |
---|---|
entire_heap |
SecureHeapAndRange
|
响应
名称 | 类型 |
---|---|
payload |
SecureMem_GetPhysicalSecureHeapProperties_Result
|
GetPhysicalSecureHeaps
获取通过 TEE 配置其物理范围的任何安全堆的物理地址和长度。
目前,这些地址是固定的物理地址和长度,并且位置通过 TEE 进行连接。
如果不需要任何特定于堆的每 VMO 设置或拆解,此方法优于 RegisterHeap()。
在 Securemem 驱动程序成功响应此请求之前,该物理范围必须受到 TEE 保护/保护。
Sysmem 应仅调用一次此函数。返回零堆不是失败。
错误数:
- ZX_ERR_BAD_STATE - 被调用了多次。
- ZX_ERR_INTERNAL - 常规内部错误(例如与 TEE 通信时不会生成 zx_status_t 错误)。
- 也可能是其他错误,例如通信故障或服务器传播 zx_status_t 故障
请求
<EMPTY>
响应
名称 | 类型 |
---|---|
payload |
SecureMem_GetPhysicalSecureHeaps_Result
|
ModifySecureHeapPhysicalRange
对于通过 sysmem 设置的物理范围,这个从 sysmem 到安全 mem 驱动程序的请求会传达要修改的物理范围及其新的基数和长度。
只有 sysmem 可以调用此属性,因为只有 sysmem 会通过 RegisterSecureMem() 将提供此协议的 FIDL 通道的客户端端交给 RegisterSecureMem()。securemem 驱动程序是此协议的服务器端。
Securemem 驱动程序必须将范围配置为仅涵盖新的偏移量,然后才能成功响应此消息。
失败时,securemem 驱动程序必须确保范围未更改。
如果 dynamic_protection_ranges 为 false,系统则不得调用此方法。如果 !is_mod_protected_range_available,则系统不得调用此方法。
如果 dynamic_protection_ranges 为 true,则 sysmem 可以在调用时存在的各种范围内重复调用此属性。
只能在其中一端修改该范围,但不能同时修改两者。 如果范围变短,而其他有效范围没有涵盖未覆盖的块,则整个范围变短的整个范围的任何进行中 DMA 都可能会中断(总线锁定或类似情况),因此调用方必须确保没有 DMA 正在进行任何正在缩短的范围的 DMA,除非修改中未被修改覆盖的任何有效范围内的块都没有发生中断。
如果某个范围被修改为长度小于等于零,则该范围被删除。
错误数:
- ZX_ERR_BAD_STATE - 在 !dynamic_protection_ranges 时调用。
- ZX_ERR_INVALID_ARGS - 意外堆、old_range 或 new_range 但不符合 Protect_range_granularity,或 old_range 和 new_range 在开始和结束方面有所不同(不允许)。
- ZX_ERR_INTERNAL - 常规内部错误(例如与 TEE 通信时不会生成 zx_status_t 错误)。
- ZX_ERR_NOT_FOUND - 未找到指定的范围。
- 其他错误,例如由于通信失败或服务器传播 zx_status_t 故障。
请求
名称 | 类型 |
---|---|
range_modification |
SecureHeapAndRangeModification
|
响应
名称 | 类型 |
---|---|
payload |
SecureMem_ModifySecureHeapPhysicalRange_Result
|
ZeroSubRange
通过 AddSecureHeapPhysicalRange() 添加的当前物理范围的子范围为零。该子范围必须恰好在一个物理范围中覆盖,且不得与任何其他物理范围重叠。
is_covering_range_extended - 如果为 true,覆盖范围必须是通过 AddSecureHeapPhysicalRange() 明确创建的范围之一(可能是自该范围起经过了修改)。如果为 false,覆盖范围不得是通过 AddSecureHeapPhysicalRange() 明确创建的范围之一,但覆盖范围必须作为未通过 AddSecureHeapPhysicalRange() 创建的覆盖范围存在。覆盖范围通常是由 TEE 配置的堆的整个物理范围(或覆盖更多的范围),并且其配置已通过 GetPhysical() 传递给 Hesmem。
正在进行的 DMA 不会因此请求而中断。
请求
名称 | 类型 |
---|---|
is_covering_range_explicit |
bool
|
heap_range |
SecureHeapAndRange
|
响应
名称 | 类型 |
---|---|
payload |
SecureMem_ZeroSubRange_Result
|
结构
BufferCollectionConstraints
在 fuchsia.sysmem/constraints.fidl 中定义
对 BufferCollection 参数的限制。您可以为每个参与者指定这些限制。Sysmem 服务实现了来自多个参与者的约束汇总。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
usage |
BufferUsage
|
该用法仅用作提示,以便在存在多个兼容选项时,帮助系统选择更优的 PixelFormat 或类似选项。 聚合 BufferCollectionConstraints 时,这些值按位或运算。 除非整个 BufferCollectionConstraints 在逻辑上为 null,但因为 !has_constraints 导致的,否则必须至少指定一个使用位。 |
无默认取景方式 |
min_buffer_count_for_camping |
uint32
|
每个参与者可以同时保留的缓冲区,供参与者在非瞬态时间(露营启用)内专门使用。 例如,视频解码器会指定(至少)最大参考帧数量 + 当前被解码的帧的最大数量。 参与者在驻留处的缓冲区不得超过此处指定的缓冲区(除非是非常临时),否则处理可能会卡住。 聚合 BufferCollectionConstraints 时,这些值会相加。 在测试场景中,如果驻留在超过此值的缓冲区内的任何较长时间,可能(理想情况下)会被标记为失败。在测试场景中,为参与者同时提供的缓冲区数量不能超过此值。 |
无默认取景方式 |
min_buffer_count_for_dedicated_slack |
uint32
|
每个参与者因 Slack 而需要的最小缓冲区数,以实现更好的处理重叠 / 更高的性能。 聚合 BufferCollectionConstraints 时,这些值会相加。 参与者通常应在此处指定 0 或 1。通常,如果 min_buffer_count_for_camping 已经足以让参与者在有点落后时 100% 的时间都处于忙碌状态,那么当参与者有点落后时,通常应该指定 0 或 1;如果缓冲区比最少露营原因所严格要求的 1 多,则可以留出 1 作为适当的缓冲区,此时可留出足够的空闲时间而不是 100% 的剩余时间。 在测试场景中,系统可能会强制将此字段设为 0,并且所有参与者都应继续工作而不会卡住。如果出于前向进度原因需要缓冲区,则应在 min_buffer_count_for_camping 中计入该缓冲区。 |
无默认取景方式 |
min_buffer_count_for_shared_slack |
uint32
|
与 min_buffer_count_for_dedicated_slack 类似,但以下情况除外:聚合这些值的最大值(而非添加值)。此处的值未与任何参与者的 min_buffer_count_for_dedicated_slack 共享。 如果参与者希望确保总体有一定的空闲时间,但不需要专门留出一定的空闲时间,则可以在此处指定大于 0 的值。 使用 min_buffer_count_for_dedicated_slack 或 min_buffer_count_for_shared_slack(或两者皆有)的选择通常与额外 Slack 对性能的提升程度相关。 在测试场景中,系统可能会强制将此字段设为 0,并且所有参与者都应继续工作而不会卡住。如果出于前向进度原因需要缓冲区,则应在 min_buffer_count_for_camping 中计入该缓冲区。 |
无默认取景方式 |
min_buffer_count |
uint32
|
不幸的是,如果您特别挑剔,可能需要一个小范围的 package_count,甚至是特定的 buffer_count。除非参与者确实必须设置此字段以限制整个 BufferCollectionInfo_2.buffer_count,否则此字段应保持为 0。任何此类参与者仍应填写上面的 min_buffer_count_for_* 字段。 |
无默认取景方式 |
max_buffer_count |
uint32
|
0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
has_buffer_memory_constraints |
bool
|
对 BufferCollectionSettings.buffer_settings 的约束。 想要指定 image_format_constraints_count > 1 的参与者通常会通过 image_format_constraints 隐式指定最小缓冲区大小,并且可能通过 buffer_memory_constraints 仅指定缓冲区大小上限。 |
无默认取景方式 |
buffer_memory_constraints |
BufferMemoryConstraints
|
无默认取景方式 | |
image_format_constraints_count |
uint32
|
针对存储在 BufferCollection 缓冲区中的图像的图片格式参数的可选限制。这包括像素格式和图片布局。这些约束条件是按像素格式设置的,因此允许设置多个约束条件。列表中的条目必须具有唯一的 pixel_formats。 聚合时,仅保留具有非零 image_format_constraints_count(以及非 Null)BufferCollectionConstraints 的所有参与者指定的像素格式。 |
无默认取景方式 |
image_format_constraints |
[32]
|
无默认取景方式 |
BufferCollectionConstraintsAuxBuffers
在 fuchsia.sysmem/constraints.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
need_clear_aux_buffers_for_secure |
bool
|
如果为 true,则仅当所有具有 BufferMemoryConstraints 的参与者都指定 allow_clear_aux_buffers_for_secure 时,才能选择安全堆。如果“need”为 true,“allow”也必须为 true。 如果为 false,参与者仍然可以工作,即使使用安全内存(取决于支持的堆)时,参与者仍然可以工作,没有清除 Aux 缓冲区。 |
无默认取景方式 |
allow_clear_aux_buffers_for_secure |
bool
|
如果为 true,参与者将根据参与者的角色使用清除的辅助缓冲区(如果已分配)。如果参与者是生产方,则参与者生产方将使用透明(未加密、未受 DRM 保护)的字节填充清除 Aux 缓冲区,并使用不模拟起始代码的数据(例如 0xFF)填充受保护的字节。 如果参与者从未发送 BufferCollectionConstraintsAuxBuffers,则当参与者指定只读使用时,“allow”为 true。 如果具有写入权限的参与者未指定或为 false,则只要有任何参与者指定了 need_clear_aux_buffers_for_secure true,系统就无法分配缓冲区收集。 |
无默认取景方式 |
BufferCollectionInfo 资源
在 fuchsia.sysmem/collections_deprecation.fidl 中定义
有关缓冲区集合及其缓冲区的信息。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
buffer_count |
uint32
|
集合中的缓冲区数量。 |
无默认取景方式 |
format |
BufferFormat
|
描述缓冲区内容的表示方式。集合中的所有缓冲区均采用相同的格式。 |
无默认取景方式 |
vmos |
vmo[64]
|
集合中每个缓冲区的 VMO 句柄。 仅当缓冲区由 VMO 提供支持时,VMO 才会显示。 如果存在,则 |
无默认取景方式 |
vmo_size |
uint64
|
提供的每个 VMO 的大小。 仅当缓冲区由 VMO 提供支持时,此属性才会显示。 |
0 |
BufferCollectionInfo_2 资源
在 fuchsia.sysmem/constraints.fidl 中定义
有关缓冲区集合及其缓冲区的信息。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
buffer_count |
uint32
|
缓冲区总数。 |
无默认取景方式 |
settings |
SingleBufferSettings
|
这些设置会应用于初始缓冲区分配中的所有缓冲区。 |
无默认取景方式 |
buffers |
[64]
|
VMO 处理集合中的每个缓冲区(以及 vmo_usable_start 偏移)。 如果存在,则索引 所有缓冲区 VMO 句柄的大小和访问权限都相同。大小位于 settings.buffer_settings.size_bytes 中。 VMO 访问权限是根据客户端在分配缓冲区集合时指定的使用情况来确定的。例如,表示为只读使用情况的客户端将收到没有写入权限的 VMO。此外,在调用 BufferCollectionToken.Duplicate() 时,此参数还可以减弱权限。 |
无默认取景方式 |
BufferFormat
在 fuchsia.sysmem/formats_deprecation.fidl 中定义
描述缓冲区内容的表示方式。每种类型的缓冲区都由各自的表进行描述。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
tag |
uint32
|
由于此结构体曾经是单个成员联合,因此我们保留了标记,以避免任何传输格式更改。该标记必须设置为 |
0 |
image |
ImageFormat
|
无默认取景方式 |
BufferMemoryConstraints
在 fuchsia.sysmem/constraints.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
min_size_bytes |
uint32
|
0 | |
max_size_bytes |
uint32
|
0 被视为 0xFFFFFFFF。 |
4294967295 |
physically_contiguous_required |
bool
|
false | |
secure_required |
bool
|
如果为 true,则至少有一位参与者需要安全内存。 聚合 BufferCollectionConstraints 时,这些值为布尔值或。 |
false |
ram_domain_supported |
bool
|
默认情况下,参与者必须确保 CPU 能够在不执行缓存操作的情况下读取或写入缓冲区数据。如果它们支持使用 RAM 域,则数据必须在 RAM 中可用(通过 CPU 缓存状态,使 RAM 数据不会因脏 CPU 缓存行向 RAM 写入错误数据而损坏),使用 CPU 执行读取操作的使用方必须在读取之前使 CPU 缓存失效(生产方无法保证零过时的“干净”缓存行) |
false |
cpu_domain_supported |
bool
|
true | |
inaccessible_domain_supported |
bool
|
false | |
heap_permitted_count |
uint32
|
可选的堆约束条件。不关心在哪个堆内存上分配的参与者应将此字段保留为 0。 |
无默认取景方式 |
heap_permitted |
[32]
|
无默认取景方式 |
BufferMemorySettings
在 fuchsia.sysmem/constraints.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
size_bytes |
uint32
|
无默认取景方式 | |
is_physically_contiguous |
bool
|
无默认取景方式 | |
is_secure |
bool
|
无默认取景方式 | |
coherency_domain |
CoherencyDomain
|
无默认取景方式 | |
heap |
HeapType
|
从中分配缓冲区的特定堆。 有关堆标识符值的信息,请参阅上述文件。 |
无默认取景方式 |
BufferUsage
在 fuchsia.sysmem/usages.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
none |
uint32
|
无默认取景方式 | |
cpu |
uint32
|
无默认取景方式 | |
vulkan |
uint32
|
无默认取景方式 | |
display |
uint32
|
无默认取景方式 | |
video |
uint32
|
无默认取景方式 |
ColorSpace
在 fuchsia.sysmem/image_formats.fidl 中定义
描述图片中的像素应如何呈现。简单的颜色空间只需要一个类型。参数颜色空间可能需要其他属性。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
type |
ColorSpaceType
|
无默认取景方式 |
FormatModifier
在 fuchsia.sysmem/format_modifier.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
value |
uint64
|
高 8 位是 FormatModifierVendor 枚举中分配的供应商代码。低 56 位由供应商定义。 出于兼容性原因,此字段和此字段中的值以这种方式定义。 |
无默认取景方式 |
ImageFormat
在 fuchsia.sysmem/image_formats_Deprecated.fidl 中定义
描述图片的表示方式。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
width |
uint32
|
行宽(以像素为单位)。 |
无默认取景方式 |
height |
uint32
|
行数。 |
无默认取景方式 |
layers |
uint32
|
多层图像中的层数。 如果未指定,则默认为 1。 |
1 |
pixel_format |
PixelFormat
|
像素格式。 |
无默认取景方式 |
color_space |
ColorSpace
|
颜色空间。 |
无默认取景方式 |
planes |
[4]
|
无默认取景方式 |
ImageFormatConstraints
在 fuchsia.sysmem/constraints.fidl 中定义
描述缓冲区中图片数据布局的约束条件。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
pixel_format |
PixelFormat
|
应用以下约束条件的 PixelFormat。一个参与者可能有多个受支持的 PixelFormat,在这种情况下,参与者可以使用 ImageFormatConstraints 列表,每个 PixelFormat 包含一个条目。ImageFormatConstraints 的其他字段因 PixelFormat 而异的情况并不罕见,例如,线性格式支持的大小上限小于平铺格式。 |
无默认取景方式 |
color_spaces_count |
uint32
|
Empty 表示错误。有多余的条目是错误的。任意排序不是错误。 |
无默认取景方式 |
color_space |
[32]
|
无默认取景方式 | |
min_coded_width |
uint32
|
允许的最小宽度(以像素为单位)。 例如,视频解码器参与者可以将此字段设置为数据流可能指定的最小 coded_width。相比之下,required_min_coded_width 将设为数据流指定的当前编码宽度。而 min_coded_width 通过获取最大值进行聚合,而 required_min_coded_width 通过获取最小值 另请参阅 required_min_coded_width。 |
无默认取景方式 |
max_coded_width |
uint32
|
最大宽度(以像素为单位)。例如,scape 可以(直接或通过子参与者)将此字段设置为可合成的最大宽度。0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
min_coded_height |
uint32
|
高度下限(以像素为单位)。例如,视频解码器参与者可以将此字段设置为数据流指定的 coding_height。 |
无默认取景方式 |
max_coded_height |
uint32
|
高度上限(以像素为单位)。例如,scape 可以(直接或通过子参与者)将此字段设置为可合成的最大高度。0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
min_bytes_per_row |
uint32
|
必须大于等于平面 0 的 min_coded_width 隐含的值。 |
无默认取景方式 |
max_bytes_per_row |
uint32
|
必须大于等于平面 0 的 max_coded_width 所隐含的值。0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
max_coded_width_times_coded_height |
uint32
|
以像素为单位的最大图像区域通过 BufferSettings.size_bytes 间接限制,也可通过此字段直接强制执行。0 被视为 0xFFFFFFFF。 |
4294967295 |
layers |
uint32
|
多层图像中的层数。 0 会被视为 1。 |
1 |
coded_width_divisor |
uint32
|
coding_width % width_divisor 必须为 0。 0 会被视为 1。 |
1 |
coded_height_divisor |
uint32
|
coding_height 高度除数百分比必须为 0。 0 会被视为 1。 |
1 |
bytes_per_row_divisor |
uint32
|
每个行的 bytes_per_row_divisor 必须为 0。 0 会被视为 1。 |
1 |
start_offset_divisor |
uint32
|
vmo_usable_start % start_offset_divisor 必须为 0。 0 会被视为 1。 |
1 |
display_width_divisor |
uint32
|
display_width % display_width_divisor 必须为 0。 0 会被视为 1。 |
1 |
display_height_divisor |
uint32
|
display_height % display_height_divisor 必须为 0。 0 会被视为 1。 |
1 |
required_min_coded_width |
uint32
|
required_尺寸边界。 与开头没有“required_”的相应字段不同,这些字段(设置为非零值时)表示要求生成的汇总非 required_ 字段指定一个空间,该空间完全包含每个参与者的 required_ 字段表示的空间。 例如,制作者视频解码器非常希望消费者愿意接受任何内容,而视频解码器其实并不希望限制数据流中可能看到的维度的潜在空间,消费者也可以接受这些维度,但视频解码器需要确保生成的维度范围至少包含从数据流解码的当前维度。 同样,如果发起者想到某种动态维度场景,则可能希望预先要求参与者同意至少处理该场景中发起者预期的维度范围(否则应尽早失败,也可能在请求空间较小的情况下重试)。 提供方或发起者设置这些字段要比使用者设置这些字段更常见。 非必需字段通过取交集进行汇总,而 required_ 字段通过取并集进行汇总。 如果已设置,required_max_coded_width 和 required_max_coded_height 将使分配的缓冲区足够大,以容纳尺寸为 required_max_coded_width * required_max_coded_height 的图片。 TODO(dustingreen):更轻松地分配最小大小的缓冲区,这些缓冲区可以(可选)处理最大尺寸的 90 度旋转版本 / 其他主要宽高比的备用必需边界。0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
required_max_coded_width |
uint32
|
无默认取景方式 | |
required_min_coded_height |
uint32
|
0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
required_max_coded_height |
uint32
|
无默认取景方式 | |
required_min_bytes_per_row |
uint32
|
0 被视为 0xFFFFFFFF。 |
无默认取景方式 |
required_max_bytes_per_row |
uint32
|
无默认取景方式 |
ImageFormat_2
在 fuchsia.sysmem/constraints.fidl 中定义
描述图片的表示方式。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
pixel_format |
PixelFormat
|
像素格式。 |
无默认取景方式 |
coded_width |
uint32
|
缓冲区中存在的行宽度(以像素为单位)。必须大于等于 display_width。 可以小于 stride_bytes 所隐含的宽度。 |
无默认取景方式 |
coded_height |
uint32
|
行数。必须 >= display_height。 |
无默认取景方式 |
bytes_per_row |
uint32
|
平面 0 的步长(以字节为单位)。平面 0 以外的平面(如有,具体取决于 pixel_format)与平面 0 的步长具有已知的固定关系。对于 Intel 平铺纹理,步长针对纹理的线性版本。 |
无默认取景方式 |
display_width |
uint32
|
要显示的行宽(以像素为单位)。此值可以设为 <= coded_width。任何剪裁操作发生在图片右侧(而非左侧)。 |
无默认取景方式 |
display_height |
uint32
|
要显示的行数。此值可以为 <= coded_height,在底部(而非顶部)进行任何剪裁。 |
无默认取景方式 |
layers |
uint32
|
多层图像中的层数。 |
1 |
color_space |
ColorSpace
|
颜色空间。 |
无默认取景方式 |
has_pixel_aspect_ratio |
bool
|
Pixel_aspect_ratio_width : pixel_aspect_ratio_height 是亮度(也称为 Y)样本的像素宽高比(又称为示例宽高比,也称为 SAR)。值为 1:1 均方像素的 pixel_aspect_ratio。pixel_aspect_ratio 为 2:1 意味着,像素的显示宽度是高度的两倍。编解码器实现应在必要时通过减少比例(将两者均除以 GCF)确保这两个值相对优质。 当 has_pixel_aspect_ratio == false 时,pixel_aspect_ratio 未知。 在某些情况下,默认值为 1:1,但与往常一样,使用方可能会通过 OOB 均值确定实际的 pixel_aspect_ratio。 |
false |
pixel_aspect_ratio_width |
uint32
|
1 | |
pixel_aspect_ratio_height |
uint32
|
1 |
ImagePlane
在 fuchsia.sysmem/image_formats_Deprecated.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
byte_offset |
uint32
|
平面起点到图片开头的字节偏移量。 |
无默认取景方式 |
bytes_per_row |
uint32
|
每行的步长(以字节为单位)。 仅对线性缓冲区格式有意义。 |
无默认取景方式 |
ImageSpec
在 fuchsia.sysmem/image_formats_Deprecated.fidl 中定义
描述在分配某种所需形式的图片时存在的限制。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
min_width |
uint32
|
最小宽度(以像素为单位)。 |
无默认取景方式 |
min_height |
uint32
|
高度下限(以像素为单位)。 |
无默认取景方式 |
layers |
uint32
|
多层图像中的层数。 如果未指定,则默认为 1。 |
1 |
pixel_format |
PixelFormat
|
像素格式。 |
无默认取景方式 |
color_space |
ColorSpace
|
颜色空间。 |
无默认取景方式 |
Node_IsAlternateFor_Response
在 fuchsia.sysmem/collection.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
is_alternate |
bool
|
无默认取景方式 |
PixelFormat
在 fuchsia.sysmem/image_formats.fidl 中定义
描述图片内像素的表示方式。 简单的格式只需要一个类型。参数像素格式可能需要其他属性。
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
type |
PixelFormatType
|
无默认取景方式 | |
has_format_modifier |
bool
|
此布尔值实际上使 format_modifier 为可选项,以满足“ForDeprecatedCBindings”的要求,进而满足“FIDL 简单 C 绑定”。 |
无默认取景方式 |
format_modifier |
FormatModifier
|
无默认取景方式 |
SecureMem_AddSecureHeapPhysicalRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SecureMem_DeleteSecureHeapPhysicalRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SecureMem_GetPhysicalSecureHeapProperties_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
properties |
SecureHeapProperties
|
无默认取景方式 |
SecureMem_GetPhysicalSecureHeaps_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
heaps |
SecureHeapsAndRanges
|
无默认取景方式 |
SecureMem_ModifySecureHeapPhysicalRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SecureMem_ZeroSubRange_Response
在 fuchsia.sysmem/secure_mem.fidl 中定义
<EMPTY>
SingleBufferInfo 资源
在 fuchsia.sysmem/constraints.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
settings |
SingleBufferSettings
|
无默认取景方式 | |
buffer |
VmoBuffer
|
无默认取景方式 |
SingleBufferSettings
在 fuchsia.sysmem/constraints.fidl 中定义
在初始缓冲区分配之后,允许关闭旧缓冲区并分配新的缓冲区。分配新缓冲区时,其设置可能与集合中的其他缓冲区不同,并且单个缓冲区的设置将使用以下结构体通过 OnSingleBufferAlloud() 传递:
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
buffer_settings |
BufferMemorySettings
|
无默认取景方式 | |
has_image_format_constraints |
bool
|
对于包含非未压缩图片数据的缓冲区,不会设置此字段。对于包含未压缩图片数据的缓冲区,可以设置此字段。 至少目前,更改 PixelFormat 需要重新分配缓冲区。 |
无默认取景方式 |
image_format_constraints |
ImageFormatConstraints
|
无默认取景方式 |
VmoBuffer 资源
在 fuchsia.sysmem/constraints.fidl 中定义
字段 | 类型 | 说明 | 默认 |
---|---|---|---|
vmo |
handle<vmo>?
|
同一个 VMO 可以由多个 CodecBuffer(只能由同一个 buffer_lifetime_ordinal 构成)使用,但每个 vmo 句柄必须是单独的句柄。 如果 BufferCollectionInfo_2 中的 VmoBuffer 不小于 BufferCollectionInfo_2.buffer_count,则 vmo 字段可为 0。 |
无默认取景方式 |
vmo_usable_start |
uint64
|
第一个可用字节的 VMO 内的偏移量。必须小于 VMO 的大小(以字节为单位),并在 VMO 结束之前留出足够的空间来容纳 BufferMemorySettings.size_bytes。 |
无默认取景方式 |
枚举
CoherencyDomain 严格
类型:uint32
在 fuchsia.sysmem/constraints.fidl 中定义
“无法访问”仅适用于无法基于 CPU 访问缓冲区的情况。即使 Secure_required 缓冲区只有在 CPU 在安全模式(或类似模式)下运行时,只能由 CPU 访问,secure_required 缓冲区仍然可以有 CoherencyDomain Cpu 或 RAM。相反,即使无法使设备(物理或虚拟设备)将数据从无法访问的缓冲区复制到 CPU 可见的缓冲区,也无法从 CPU 访问的设备本地内存属于 CoherencyDomain 无法访问。
名称 | 值 | 说明 |
---|---|---|
CPU |
0 |
|
RAM |
1 |
|
无法访问 |
2 |
ColorSpaceType 严格
类型:uint32
在 fuchsia.sysmem/image_formats.fidl 中定义
此列表为颜色空间标准的每个变体提供了单独的条目。
因此,如果我们要添加对 RGB 变体 709 的支持,则会在此列表中为该变体添加单独的条目。同样,对于 2020 或 2100 的 RGB 变体。同样,对于 2020 的 YcCbcCrc 变体。对 2100 的 ICtCp 变体也是如此。
给定的 ColorSpaceType 可能允许与提供与 ColorSpaceType 官方规范兼容的每样本位数的 PixelFormatType 一起使用。并非所有规范有效的组合都受支持。请参阅 ImageFormatIsSupportedColorSpaceForPixelFormat(),了解最佳支持程度,但该函数返回“true”并不能保证任何给定的参与者组合都将支持所需的 ColorSpaceType 和 PixelFormatType 组合。
sysmem 服务有助于查找相互支持的组合,并分配适当的缓冲区。
ColorSpaceType 的规范不会隐式扩展,以支持超出标准的每样本位数(R、G、B 或 Y 样本)。例如,对于 2020 和 2100,系统不支持每 Y 样本 8 位,因为 2020 或 2100 的规范中不符合 Y 样本 8 位。如果系统参与者尝试通告对非标准的 PixelFormat + ColorSpace 的支持,将会导致 sysmem 拒绝组合并无法分配(故意,这是强烈阻止指定定义不足的组合)。
名称 | 值 | 说明 |
---|---|---|
INVALID |
0 |
不是有效的颜色空间类型。 |
SRGB |
1 |
sRGB |
REC601_NTSC |
2 |
601 NTSC(“525 line”)YCbCr 原色,窄 |
REC601_NTSC_FULL_RANGE |
3 |
601 NTSC(“525 line”)YCbCr 原色,宽 |
REC601_PAL |
4 |
601 PAL(“625 行”)YCbCr 原色,窄 |
REC601_PAL_FULL_RANGE |
5 |
601 PAL(“625 行”)YCbCr 原色,宽 |
REC709 |
6 |
709 YCbCr(非 RGB) |
REC2020 |
7 |
2020 YCbCr(非 RGB,非 YcCbcCrc) |
REC2100 |
8 |
2100 YCbCr(非 RGB,非 ICtCp) |
PASS_THROUGH |
9 |
像素格式不表示颜色,或者位于无法由此枚举中的其他条目描述的应用专用颜色空间中。 |
DO_NOT_CARE |
4294967294 |
Sysmem 客户端明确指出,sysmem 客户端并不在意选择 / 使用哪个颜色空间。 添加数量:10
|
堆类型(严格)
类型:uint64
在 fuchsia.sysmem/constraints.fidl 中定义
已知的堆类型。 设备专用类型应设置位 60。顶级位已预留,不应设置。
名称 | 值 | 说明 |
---|---|---|
SYSTEM_RAM |
0 |
|
AMLOGIC_SECURE |
1152921504606912512 |
用于 amlogic 保护内存的堆。 |
AMLOGIC_SECURE_VDEC |
1152921504606912513 |
在解密和视频解码之间用于 Amlogic 保护内存的堆。 |
GOLDFISH_DEVICE_LOCAL |
1152921504606978048 |
goldfish vulkan 将其用于设备本地内存的堆。 |
GOLDFISH_HOST_VISIBLE |
1152921504606978049 |
goldfish vulkan 将其用于主机可见内存的堆。 |
框架 |
1152921504607043585 |
用于显示帧缓冲区的堆。由限制为位于特定物理地址的单个帧缓冲区的显示驱动程序使用。帧缓冲区堆可为帧缓冲区创建缓冲区集合,并在这些驱动程序中启用 Sysmem 支持。 |
PixelFormatType 严格
类型:uint32
在 fuchsia.sysmem/image_formats.fidl 中定义
格式名称中通道的顺序反映了通道的实际布局方式。
其中每个值都有各自的专属颜色空间,这与 Vulkan 相反。
它应与 fuchsia.sysmem2.PixelFormatType 保持同步。
名称 | 值 | 说明 |
---|---|---|
INVALID |
0 |
|
R8G8B8A8 |
1 |
仅限 RGB,每个 R/G/B/A 样本 8 位。与 VK_FORMAT_R8G8B8A8_UNORM 兼容。 |
BGRA32 |
101 |
32bpp BGRA,1 个平面。仅限 RGB,每个 B/G/R/A 样本 8 位。 与 VK_FORMAT_B8G8R8A8_UNORM 兼容。 |
I420 |
102 |
仅限 YUV,每个 Y 样本 8 位。与 VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM 兼容。 |
M420 |
103 |
仅限 YUV,每个 Y 样本 8 位 与任何 Vulkan 格式都不兼容。 |
NV12 |
104 |
仅限 YUV,每个 Y 样本 8 位。与 VK_FORMAT_G8_B8R8_2PLANE_420_UNORM 兼容。 |
YUY2 |
105 |
仅限 YUV,每个 Y 样本 8 位。与 VK_FORMAT_G8B8G8R8_422_UNORM 兼容。 |
MJPEG |
106 |
|
YV12 |
107 |
仅限 YUV,每个 Y 样本 8 位 与具有 B 和 R 调配的 VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM 兼容。 |
BGR24 |
108 |
24bpp BGR,1 个平面。仅限 RGB,每个 B/G/R 样本 8 位。与 VK_FORMAT_B8G8R8_UNORM 兼容。 |
RGB565 |
109 |
16bpp RGB,1 个平面。5 位 R、6 位 G、5 位 B 与 VK_FORMAT_R5G6B5_UNORM_PACK16 兼容。 |
RGB332 |
110 |
8bpp RGB,1 个平面。3 位 R、3 位 G、2 位 B 与任何 Vulkan 格式都不兼容。 |
RGB2220 |
111 |
8bpp RGB,1 个平面。2 位 R、2 位 G、2 位 B 与任何 Vulkan 格式都不兼容。 |
L8 |
112 |
8bpp,仅限亮度(红色、绿色和蓝色的值相同)。 与 VK_FORMAT_R8_UNORM 兼容。 |
R8 |
113 |
8bpp,仅限红色(绿色和蓝色将被解释为 0)。 与 VK_FORMAT_R8_UNORM 兼容。 |
R8G8 |
114 |
16bpp RG,1 个平面。8 位 R、8 位 G。 与 VK_FORMAT_R8G8_UNORM 兼容。 |
A2R10G10B10 |
115 |
32bpp RGBA,1 个平面。2 位 A,10 位 R/G/B。 与 VK_FORMAT_A2R10G10B10_UNORM_PACK32 兼容。 |
A2B10G10R10 |
116 |
32bpp BGRA,1 个平面。2 位 A,10 位 R/G/B。 与 VK_FORMAT_A2B10G10R10_UNORM_PACK32 兼容。 |
DO_NOT_CARE |
4294967294 |
Sysmem 客户端明确指出,sysmem 客户端并不在意选择 / 使用哪种像素格式。设置此值时,sysmem 客户端不得设置 format_modifier_value。 添加数量:10
|
表
BufferCollectionTokenGroupCreateChildRequest 资源
在 fuchsia.sysmem/collection.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
token_request |
server_end<BufferCollectionToken>
|
必须设置。 |
2 |
rights_attenuation_mask |
uint32
|
如果未设置,则默认值为 ZX_RIGHT_SAME_RIGHTS。 |
SecureHeapAndRange
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
heap |
HeapType
|
|
2 |
range |
SecureHeapRange
|
SecureHeapAndRangeModification
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
heap |
HeapType
|
|
2 |
old_range |
SecureHeapRange
|
|
3 |
new_range |
SecureHeapRange
|
SecureHeapAndRanges
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
heap |
HeapType
|
这是安全/受保护的堆。 |
2 |
ranges |
vector<SecureHeapRange>[128]
|
物理范围列表。此列表必须按 Physical_address 排序(由低到高),且不得有任何重叠的范围。允许直接相邻的范围(不重叠)。 |
SecureHeapProperties
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
heap |
HeapType
|
为方便起见,此处重复介绍了 HeapType。 |
2 |
dynamic_protection_ranges |
bool
|
如果为 true,则可以针对同一堆多次调用 SetPhysicalSecureHeap()。如果为 false,则只允许一次 SetPhyscialSecureHeap() 调用,并且不允许调用 DeleteSecureHeapPhysicalRange() 或 ModifySecureHeapPhysicalRange()。即使此属性为 false,SecureMem 服务器(驱动程序)仍负责在热重新启动之前去掉保护,前提是受保护的范围在热重新启动期间不会被清理。 |
3 |
protected_range_granularity |
uint32
|
保护范围的粒度。如果起始粒度与结束或长度的粒度不同,则这是这些值中的最大粒度值。 此值必须是 2 的幂。客户端不得请求指定较小粒度的范围。 该值必须至少为 zx_system_page_size(),即使硬件可以实现更小的粒度也是如此。 |
4 |
max_protected_range_count |
uint64
|
如果 SecureMem 服务器需要进行任何此类模拟,则 SecureMem 服务器不应计算其内部用于从范围集 A 到范围集 B 的预留范围的数量。通常不需要 SecureMem 服务器进行此类模拟。如果 SecureMem 服务器预留了任何范围,则这些预留的范围无法供 SecureMem 客户端使用。 如果范围数量仅受可用内存的限制,SecureMem 服务器可以针对此值报告 0xFFFFFFFFFFFFFFFF。该字段必须仍然设置。与往常一样,SecureMem 服务器应确保 SetPhysicalSecureHeapRanges() 以原子方式成功或失败(完全更新或在完成之前回滚)。 |
5 |
is_mod_protected_range_available |
bool
|
如果为 true,则会实现 ModifySecureHeapPhysicalRange()。禁止在 is_mod_protected_range_available 为 false 时调用 ModifySecureHeapPhysicalRange()。请勿尝试通过调用来查看 ModifySecureHeapPhysicalRange() 是否失败来检测 ModifySecureHeapPhysicalRange() 的可用性;它可能会 ZX_PANIC()。 |
SecureHeapRange
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
physical_address |
uint64
|
必须至少与 heap_range_granularity 对齐。 |
2 |
size_bytes |
uint64
|
必须至少与 heap_range_granularity 对齐。 |
SecureHeapsAndRanges
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 字段 | 类型 | 说明 |
---|---|---|---|
1 |
heaps |
vector<SecureHeapAndRanges>[32]
|
联合
Node_IsAlternateFor_Result 严格
在 fuchsia.sysmem/collection.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
Node_IsAlternateFor_Response
|
|
2 |
err |
zx/Status
|
SecureMem_AddSecureHeapPhysicalRange_Result 严格
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
SecureMem_AddSecureHeapPhysicalRange_Response
|
|
2 |
err |
zx/Status
|
SecureMem_DeleteSecureHeapPhysicalRange_Result 严格
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
SecureMem_DeleteSecureHeapPhysicalRange_Response
|
|
2 |
err |
zx/Status
|
SecureMem_GetPhysicalSecureHeapProperties_Result 严格
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
SecureMem_GetPhysicalSecureHeapProperties_Response
|
|
2 |
err |
zx/Status
|
SecureMem_GetPhysicalSecureHeaps_Result 严格
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
SecureMem_GetPhysicalSecureHeaps_Response
|
|
2 |
err |
zx/Status
|
SecureMem_ModifySecureHeapPhysicalRange_Result 严格
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
SecureMem_ModifySecureHeapPhysicalRange_Response
|
|
2 |
err |
zx/Status
|
SecureMem_ZeroSubRange_Result 严格
在 fuchsia.sysmem/secure_mem.fidl 中定义
序数 | 变体 | 类型 | 说明 |
---|---|---|---|
1 |
response |
SecureMem_ZeroSubRange_Response
|
|
2 |
err |
zx/Status
|