我可以使用O_DIRECT进行写入请求,以避免电源故障时数据丢失吗?

时间:2011-04-23 09:03:28

标签: linux winapi io

我们希望尽力避免在电源故障期间丢失数据。所以我决定使用O_DIRECT标志打开一个文件来写入磁盘中的数据。 O_DIRECT是否意味着数据完全绕过OS缓存?如果请求向应用程序返回成功,是否表示数据必须已刷新到磁盘?如果我在一个文件系统中打开常规文件,那么FS元数据怎么样?它是否也会被立即刷新,或者是否被缓存?

顺便说一下,O_DIRECT可以在Windows中使用吗?或者Windows中是否有相应的方法?

4 个答案:

答案 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_THROUGHFILE_FLAG_NO_BUFFERING

  

如果FILE_FLAG_WRITE_THROUGH和   FILE_FLAG_NO_BUFFERING都是   指定,以便系统缓存   没有效果,那么数据是   立即刷新到磁盘没有   通过Windows系统   高速缓存即可。操作系统也是   请求硬写入   磁盘的本地硬件缓存到   持久性媒体。

答案 3 :(得分:0)

  

我可以使用O_DIRECT进行写入请求,以避免电源故障时数据丢失吗?

没有!

在Linux O_DIRECT尝试绕过操作系统缓存时,从不绕过磁盘的缓存。如果您的磁盘具有易失性写入缓存,则在突然断电期间仍然可能丢失仅在磁盘缓存中的数据!

  

O_DIRECT是否意味着数据完全绕过OS缓存?

通常,但某些Linux文件系统可能会使用O_DIRECTExt4 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"