我知道当我使用 write()
+ fsync()
(或 O_SYNC
+ write()
,我认为它们是相同的 ref #1 ref #2 ),这意味着我正在使用阻塞同步 I/O,并且 if write()
(使用 O_SYNC
) 或 fsync()
返回,这意味着数据安全地存储在设备介质(例如 SSD 的 TLC NAND)上,而不是设备缓存(例如 SSD 中的 DDRAM)。
如果我使用libaio
会怎样? (因为我想确保 libaio 发出的写入是在存储介质上而不是设备缓存上。即,我想当 io_getevents() 返回时,它可能无法确保写入是在存储介质,可能只是在设备缓存上)
- 问题 1:
fsync()
是否专门适用于同步 I/O? - 问题2:
io_submit()
之后的fsync()
是未定义的行为吗? - 问题 3:如何使异步写入安全地持久保存到设备介质而不是设备缓存(无电池支持的缓存)。
最佳答案
(这个答案只是从 Linux 的角度来看问题。其他操作系统可能有不同的行为/语义)
只要您等待任何未完成的异步 I/O 完成,您就可以发送 fsync()
并知道所有先前的 I/O 已写入稳定存储Linux 内核的最佳知识*。
does fsync() exclusively works for synchronous I/O?
这个问题没有意义。 fsync()
处理 Linux 同意已“发送”的 I/O,然后刷新设备缓存。如果您异步向内核发送 I/O,内核是否同意它已被“发送”?另请参阅最后一个问题的答案...
is fsync() after io_submit() an undefined behavior?
技术上undefined behaviour意味着从那时起任何事情都将被合法地允许发生(例如所谓的鼻守护进程)。这里的情况并非如此,但我认为您正在问第一个问题,因此答案仍然成立。
how to make asynchronous write safely persisted to the device medium rather than device cache (no battery-backed cache).
如果您在使用libaio
时遇到困难,您可以通过等待所有未完成的I/O完成然后发送fsync()
并等待来手动构建屏障为此或( as mentioned in a comment )。另一种 libaio
技术是在 io_submit()
期间设置 RWF_SYNC
标志。如果您使用io_uring
您还有另一个选择,因为您可以使用它的链接,并且它具有异步 fsync
操作 (IORING_OP_FSYNC
)。
* 我排除了发生错误的情况,因为它们相当复杂。请参阅Writing programs to cope with I/O errors causing lost writes on Linux详细解释。
关于io - 如果我使用 libaio + fsync() 会怎样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66073136/