我们希望尽力避免在电源故障期间丢失数据。所以我决定使用O_DIRECT标志打开一个文件来写入磁盘中的数据。 O_DIRECT是否意味着数据完全绕过OS缓存?如果请求向应用程序返回成功,是否表示数据必须已刷新到磁盘?如果我在一个文件系统中打开常规文件,那么FS元数据怎么样?它是否也会被立即刷新,或者是否被缓存?
顺便说一下,O_DIRECT可以在Windows中使用吗?或者Windows中是否有相应的方法?
答案 0 :(得分:2)
O_DIRECT可能会做你想要的,但它会大大减慢你的I / O.
我认为只是调用fsync()或fflush()取决于你是使用直接文件描述符操作还是FILE *应该就足够了。
至于元数据问题,它取决于底层文件系统,甚至在硬件上,如果你想要更加偏执。硬盘驱动器(尤其是SSD)可能会报告操作已完成,但可能需要一段时间才能实际写入数据。
答案 1 :(得分:2)
您可以使用O_DIRECT,但对于许多应用程序,调用fdatasync()更方便。 O_DIRECT施加了很多限制,因为IO完全绕过了OS缓存。它绕过读缓存和写缓存。
对于文件系统元数据,您可以在写入文件后执行fsync()。 fsync刷新文件元数据,因此如果之后电源立即丢失,您可以确保文件不会消失(或更改其属性等)。
这些机制中的任何一种都取决于您的IO子系统不会向操作系统说明将数据保存到存储,并且在许多情况下,依赖于其他依赖于硬件的东西(例如RAID控制器电池在电源恢复之前没有耗尽)< / p>
答案 2 :(得分:1)
CreateFile
可以做到这一点。
HANDLE WINAPI CreateFile(
__in LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
);
对于dwFlagsAndAttributes
,您可以指定FILE_FLAG_WRITE_THROUGH
和FILE_FLAG_NO_BUFFERING
。
如果
FILE_FLAG_WRITE_THROUGH
和FILE_FLAG_NO_BUFFERING
都是 指定,以便系统缓存 没有效果,那么数据是 立即刷新到磁盘没有 通过Windows系统 高速缓存即可。操作系统也是 请求硬写入 磁盘的本地硬件缓存到 持久性媒体。
答案 3 :(得分:0)
我可以使用O_DIRECT进行写入请求,以避免电源故障时数据丢失吗?
在Linux O_DIRECT
尝试绕过操作系统缓存时,从不绕过磁盘的缓存。如果您的磁盘具有易失性写入缓存,则在突然断电期间仍然可能丢失仅在磁盘缓存中的数据!
O_DIRECT
是否意味着数据完全绕过OS缓存?
通常,但某些Linux文件系统可能会使用O_DIRECT
(Ext4 Wiki Clarifying Direct IO's Semantics
page warns this can happen with allocating writes)回退到缓冲I / O.
如果请求向应用程序返回成功,是否表示数据必须已刷新到磁盘?
这通常意味着磁盘已经“看到”它,但是看到上面的警告(例如,数据可能已经转移到缓冲区缓存/数据可能只在磁盘的易失性缓存中)。
如果我在一个文件系统中打开常规文件,FS元数据怎么样?它是否也会被立即刷新,或者是否被缓存?
很棒的问题!即使请求成功完成,元数据仍可能在缓存中滚动并且尚未同步到磁盘。
以上所有意味着您必须在正确的位置执行相应的fsync()
命令(并检查其结果!),以确定操作是否已达到非易失性存储。有关详细信息,请参阅https://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/和LWN article "Ensuring data reaches disk"。