基本用法

防止数据处理流水线中系统挂起

在许多情况下,事件都需要多个组件参与处理。假设您是一名驱动程序,收到的事件可能会唤醒系统,或者如果是在系统处于唤醒状态时收到的,则应阻止系统挂起。很常见的是,中断处理驱动程序可能不知道事件的重要性,并将其传递给其他驱动程序或组件。

您可以通过几种方式来管理此接力。为方便讨论,假设驱动程序 X 接收中断,并通过 FIDL 消息将事件传递给驱动程序 Y。如果 X 是驱动程序,而 Y 是非驱动程序组件,则这两个选项同样适用。

接力棒传递

解决此问题的一种方法是将接力棒随事件数据一起传递。“接力棒传递”是指接力赛的概念,参与者将物品从一人传递给另一人,以完成任务(即比赛)。

我们的接力棒可以是 LeaseToken(我们之前提到过)或 fuchsia.power.broker/LeaseControl 通道。我们将使用 LeaseToken,因为我们已经讨论过它们,并且它们比 LeaseControl 更易于使用。

当 X 收到中断时,它会执行以下操作: * 调用 ActivityGovernor.AcquireWakeLease * 确认中断 * 对事件执行任何处理,可能将其转换为新类型 * 将事件和从 AcquireWakeLease 获取的 LeaseToken 传递给 Y

此方法需要更改 X 和 Y 之间使用的协议。使用协议互锁(如下所述)不需要这样做,但有其他缺点。

事件速率较高的系统可能会发现调用 ActivityGovernor.AcquireWakeLease 的 IPC 开销过高,无法在每个事件中执行。在这些情况下,驱动程序 X 可以复制 LeaseToken(因为它实际上只是 Zircon 事件对的句柄),而不是简单地将 LeaseToken 从 X 移至 Y,然后传递副本并在某个超时期限内保留原始副本。如果选择使用超时,请谨慎选择超时时间,因为在 LeaseToken 的所有副本被丢弃之前,系统将无法暂停。强烈建议不要设置较长的超时时间。之所以使用超时时间,是因为您的事件速率较高,这意味着您应该能够选择较短的超时时间。如果您使用的是 C++,则可以使用辅助程序根据新事件的到达情况管理租约和延长超时时间。请通过调用 AcquireWakeLease 来使用该帮助程序,而不是自行与 ActivityGovernor capability 进行通信。

协议互锁

如果驱动程序 X 和驱动程序 Y 的事件传递协议包含确认或添加了确认,则可以选择“协议互锁”。协议互锁由 Y 调用 ActivityGovernor.AcquireWakeLease 实现,然后向 X 确认 Y 收到了事件。

此方法的步骤如下: * X 调用 ActivityGovernor.AcquireWakeLease * ACK 中断 * X 对事件执行任何必要的处理,可能会将其转换为新类型 * 将事件传递给 Y * Y 调用 ActivityGovernor.AcquireWakeLease * Y 向 X 确认已收到事件 * X 丢弃其 LeaseToken * Y 对事件执行任何处理 * Y 丢弃其 LeaseToken

如果协议已包含确认,协议互锁无需更改 X 和 Y 之间使用的协议。此策略增加对系统 activity 调度器的 IPC 调用次数。调用次数增加是否有意义取决于事件速率,以及 X 和 Y 是否会在超时期限内保留其 LeaseToken。如果您选择使用超时,请谨慎选择超时,因为在 LeaseToken 被丢弃之前,系统将无法暂停。强烈建议不要使用较长的超时时间,之所以使用超时时间,是因为您的事件速率较高,这意味着您应该能够选择较短的超时时间。如果您使用的是 C++,则可以使用辅助程序根据新事件的到达情况管理租约和延长超时时间。请通过调用 AcquireWakeLease 来使用该帮助程序,而不是自行与 ActivityGovernor capability 进行通信。

超时

使用超时来确保系统正确性并不是与电源框架集成的首选方案。其他选项仅将超时用作优化手段。超时可能会导致不可预测的行为,因为很难找到合适的超时值。此外,通常必须针对每种用例、产品配置和硬件配置组合调整超时设置,这使得管理超时变得一项繁重的工作。超时本身就具有争用性,因此对于任何给定的超时值,您在大多数情况下都可能赢得争用,直到突然失败。通常只有在软件部署到大量测试人员或用户群体后,才会发现失败问题,这会导致观察时感到困惑。

有时,超时是唯一可行的选项。在超时的情况下,我们将让驱动程序 X 调用 ActivityGovernor.AcquireWakeLease、ACK 中断,然后保持租约,直到超时,驱动程序 Y 永远不会看到租约。如果在超时之前收到另一个中断,驱动程序 X 只需延长超时时间,而无需获取额外的租约。如果您使用的是 C++,则可以使用辅助类,根据新中断的到达情况管理租约和延长超时时间。通过调用 AcquireWakeLease 来使用该帮助程序,而不是自行与 ActivityGovernor capability 进行通信。