问题描述
我知道当我使用 write()
+ fsync()
(或 O_SYNC
+ write()
编写文件时,我认为它们是相同的 ref #1 {{3} }),这意味着我正在使用阻塞同步 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:如何使异步写入安全地持久保存到设备介质而不是设备缓存(无电池备份缓存)。
解决方法
(这个答案只是从 Linux 的角度来看问题。其他操作系统可能有不同的行为/语义)
只要您等待任何未完成的异步 I/O 完成,您就可以向下发送您的 fsync()
并知道所有先前的 I/O 都已写入稳定存储,并尽全力了解Linux 内核*.
fsync() 是否专门用于同步 I/O?
这个问题没有意义。 fsync()
适用于 Linux 同意已“发送”的 I/O,然后还会刷新设备缓存。如果您向内核异步发送 I/O,内核是否同意它已“发送”?另请参阅最后一个问题的答案...
io_submit() 之后的 fsync() 是未定义的行为吗?
从技术上讲,undefined behaviour 意味着从那时起,任何事情都将被允许合法发生(例如所谓的鼻守护进程)。情况并非如此,但我认为您是在问您的第一个问题,因此那里的答案仍然成立。
如何使异步写入安全地持久化到设备介质而不是设备缓存(无电池备份缓存)。
如果您在使用 libaio
时遇到困难,您可以通过等待所有未完成的 I/O 完成然后发送 fsync()
并等待它或 ({{3} })。另一种 libaio
技术是在 RWF_SYNC
期间设置 io_submit()
标志。如果您使用的是 as mentioned in a comment,您还有另一个选择,因为您可以使用它的链接,并且它具有异步 fsync
操作 (IORING_OP_FSYNC
)。
* 我排除了发生错误的情况,因为它们相当复杂。有关详细说明,请参阅 io_uring
。