4

我在 FSEvents 上看到了奇怪的行为,我在恢复模式下挂载了我的驱动器,并且在重新启动时,我的流中的 fsevents 为零。我执行以下操作:

  1. 定期开机
  2. 使用 FSEventsGetCurrentEventId() 记录当前事件
  3. 以恢复模式启动并修改监视路径中的文件
  4. 重启系统

发生这种情况时,我在使用 fsevents API 时根本没有收到任何事件。它在 kFSEventStreamEventFlagHistoryDone 哨兵中发送的唯一标志,即使我在常规操作系统上进行了其他更改。

ars technica 评论似乎暗示当您安装在其他设备上时,您应该获得 kFSEventStreamEventFlagMustScanSubDirs 标志,但我没有看到这种行为。有没有人遇到过这个?有没有更好的方法来检测和处理在操作系统关闭时驱动器已安装在其他地方的情况?

更新:我尝试了从 linux 启动并修改文件系统的相同操作。无论如何,我没有得到同样奇怪的 0 事件行为,但我也没有从我更改的目录或 MustScanSubdirs 标志中得到事件。

更新 2:在这个线程中,接受的响应说当发生这种情况时,时间机器会检测到在上述情况下日志已过期。有谁知道如何检测日志是否过期?这个日期可以用来代替标志。

4

1 回答 1

2

我认为您还需要在步骤 #2 中存储 FSEvents 数据库的 UUID,并在步骤 #4 中检查它。

Apple的文档中含糊地提到了这种行为(强调添加):

注意:由于运行早期版本的 OS X(或可能的其他操作系统)的计算机可以修改磁盘,因此您应该将事件列表视为建议,而不是卷所有更改的最终列表。如果运行先前版本的 OS X 的计算机修改了磁盘,则历史日志将被丢弃。

例如,备份软件仍应定期对任何卷执行全面扫描,以确保没有任何更改漏掉。

请注意有关丢弃历史日志的信息,然后查看参考资料(已添加重点):

FSEventStreamGetLatestEventId() -> 最初,它返回创建流时提供的 sinceWhen 值;此后,在调用客户端回调之前,它会使用当前批次事件中提到的编号最高的事件 ID 进行更新。只要客户端还存储设备的 UUID(通过 FSEventsCopyUUIDForDevice() 获得),客户端就可以永久存储此值。客户端随后可以将此事件 ID 作为 FSEventStreamCreateRelativeToDevice() 的 sinceWhen 参数提供,只要其 UUID 与您存储的内容匹配。这是因为 FSEvents 服务将事件存储在一个持久的、按卷的数据库中。在这方面,事件 ID 流就像一个全局的、系统范围的时钟,但与任何特定的时基无关。

FSEventsCopyUUIDForDevice() -> 获取唯一标识该卷的 FSEvents 数据库的 UUID。如果数据库被丢弃,那么它的替换将具有不同的 UUID,以便客户端能够检测到这种情况并避免尝试使用它们存储为 FSEventStreamCreate...() 函数的 sinceWhen 参数的事件 ID。

请注意,UUID 是针对每个设备的,因此如果您在目录树中安装了任何文件系统,您可能需要获取每个文件系统的 UUID。

祝你好运!

于 2012-09-05T01:29:34.383 回答