2

我知道当我使用write()+ fsync()(或O_SYNC+ write(),我认为它们是相同的ref #1 ref #2)编写文件时,这意味着我正在使用阻塞同步 I/O,如果write()(with O_SYNC) 或fsync()返回,则意味着数据安全地保存在设备介质上(例如,用于 SSD 的 TLC NAND)而不是设备缓存(例如,SSD 中的 DDRAM)。

而如果我使用libaio呢?(因为我想确保libaio发出的写入是在存储介质上而不是在设备缓存上。也就是说,我想io_getevents()返回时,它可能不确定写入在存储介质上,可能只是在设备上缓存)

  • 问题 1:是否fsync()专门用于同步 I/O?
  • 问题2:是fsync()io_submit()未定义行为之后?
  • 问题 3:如何使异步写入安全地持久化到设备介质而不是设备缓存(没有电池支持的缓存)。
4

1 回答 1

2

(这个答案只是从 Linux 的角度来看问题。其他操作系统可能有不同的行为/语义)

只要您等待任何未完成的异步 I/O 完成,您就可以发送fsync()并知道所有以前的 I/O 都已写入稳定存储,以了解 Linux 内核*的最佳知识。

fsync() 是否专门用于同步 I/O?

这个问题没有意义。fsync()在 Linux 已同意已“发送”的 I/O 上工作,然后还刷新设备缓存。如果您向内核异步发送 I/O,内核是否同意它已“发送”?另请参阅最终问题的答案...

io_submit() 之后的 fsync() 是未定义的行为吗?

技术上未定义的行为意味着从那时起任何事情都将被允许合法地发生(例如,所谓的鼻守护程序)。这里不是这种情况,但我认为你是在问你的第一个问题,所以那里的答案仍然成立。

如何使异步写入安全地持久化到设备介质而不是设备缓存(没有电池支持的缓存)。

如果您被卡住了,libaio您可以通过等待所有未完成的 I/O 完成然后发送fsync()并等待它或(如评论中所述)来手动构建屏障。另一种libaio技术是RWF_SYNCio_submit(). 如果您正在使用io_uring,您将有另一个选择,因为您可以使用它的链接并且它具有异步fsync操作 ( IORING_OP_FSYNC)。


*我排除了发生错误的情况,因为它们相当复杂。有关详细说明,请参阅编写程序以处理导致 Linux 上丢失写入的 I/O 错误

于 2021-02-08T09:11:12.330 回答