打开(2)中的O_SYNC和O_DIRECT标志如何不同/相似?

时间:2011-02-20 07:42:32

标签: io posix synchronous

O_SYNC和O_DIRECT标志的使用和效果非常混乱,并且在平台之间似乎有所不同。从Linux手册页(参见示例here),O_DIRECT提供同步I / O,最小化缓存效果,并要求您自己处理块大小对齐。 O_SYNC只保证同步I / O.虽然两者都保证将数据写入硬盘的缓存,但我相信直接I / O操作应该比普通的同步I / O更快,因为它们绕过页面缓存(尽管FreeBSD的open(2)手册页指出使用O_SYNC时会绕过缓存。请参阅here)。

O_DIRECT和O_SYNC标志之间究竟有什么区别?一些实现建议使用O_SYNC | O_DIRECT。为什么?

4 个答案:

答案 0 :(得分:81)

单独的O_DIRECT只承诺内核将避免将数据从用户空间复制到内核空间,而是直接通过DMA写入(直接内存访问;如果可能)。数据不会进入缓存。没有严格的保证,只有在传输完所有数据后,函数才会返回。

O_SYNC保证在所有数据传输到磁盘之前调用不会返回(就操作系统而言)。这仍然不能保证数据不在硬盘写缓存中的某个位置,但它与操作系统可以保证的一样多。

O_DIRECT | O_SYNC是这些的组合,即“DMA +保证”。

答案 1 :(得分:8)

在linux 2.6下执行Actuall,o_direct是同步的,请参见手册页:

manpage of open, there is 2 section about it..

2.4以下无法保证

O_DIRECT(自Linux 2.4.10起) 尝试最小化I / O与此文件之间的缓存效果。一般情况下,这会降低性能,但在特殊情况下很有用,例如应用程序执行自己的缓存时。文件 I / O直接进入/来自用户空间缓冲区。 O_DIRECT标志本身会同步传输数据,但不会保证O_SYNC标志传输数据和必要的元数据。为了保证同步I / O,除O_DIRECT外还必须使用O_SYNC。有关进一步的讨论,请参阅下面的注释。

在raw(8)中描述了块设备的语义相似(但已弃用)的接口。

但保证在2.6以下,请参阅

O_DIRECT

O_DIRECT标志可能会对用户空间缓冲区的长度和地址以及I / O的文件偏移量施加对齐限制。在Linux中,对齐限制因文件系统和内核版本而异,可能完全不存在。但是,当前没有与文件系统无关的接口,应用程序可以发现给定文件或文件系统的这些限制。某些文件系统提供了自己的接口,例如xfsctl(3)中的XFS_IOC_DIOINFO操作。

在Linux 2.4下,传输大小,用户缓冲区和文件偏移的对齐方式都必须是文件系统逻辑块大小的倍数。在Linux 2.6下,对齐到512字节边界就足够了。

如果内存缓冲区是私有映射(即使用mmap(2)MAP_PRIVATE标志创建的任何映射),那么O_DIRECT I / O绝不能与fork(2)系统调用同时运行;这包括在堆和静态分配的缓冲区)。任何此类I / O,无论是通过异步I / O接口提交还是从进程中的其他线程提交,都应该在调用fork(2)之前完成。如果不这样做,可能会导致父进程和子进程中的数据损坏和未定义的行为。当使用带有MAP_SHARED标志的shmat(2)或mmap(2)创建O_DIRECT I / O的内存缓冲区时,此限制不适用。当内存缓冲区被建议使用带有madvise(2)的MADV_DONTFORK时,这个限制也不适用,确保在fork(2)之后它不会对子进程可用。

O_DIRECT标志是在SGI IRIX中引入的,它具有类似于Linux 2.4的对齐限制。 IRIX还有一个fcntl(2)调用来查询适当的对齐和大小。 FreeBSD 4.x引入了一个同名的标志,但没有对齐限制。

在Linux内核版本2.4.10中添加了O_DIRECT支持。较旧的Linux内核只是忽略了这个标志。某些文件系统可能没有实现该标志,如果使用EINVAL,open()将失败。

应用程序应避免将O_DIRECT和普通I / O混合到同一文件中,尤其是同一文件中的重叠字节区域。即使文件系统在这种情况下正确处理一致性问题,整体I / O吞吐量也可能比单独使用任一模式慢。同样,应用程序应避免将mmap(2)文件与直接I / O混合到同一文件中。

使用NFS的O_DIRECT行为与本地文件系统不同。较旧的内核或以某些方式配置的内核可能不支持此组合。 NFS协议不支持将标志传递给服务器,因此O_DIRECT I / O只会绕过客户端的页面缓存;服务器仍然可以缓存I / O.客户端要求服务器使I / O同步以保留O_DIRECT的同步语义。在这些情况下,某些服务器的性能会很差,尤其是在I / O大小较小的情况下。某些服务器还可以配置为向客户端提供有关已达到稳定存储的I / O的信息;这样可以避免在服务器电源故障时对数据完整性造成一定风险的性能损失。 Linux NFS客户端对O_DIRECT I / O没有对齐限制。

总之,O_DIRECT是一个潜在的强大工具,应谨慎使用。建议应用程序将O_DIRECT用作性能选项,默认情况下禁用该选项。

“O_DIRECT一直让我感到不安的是,整个界面都是愚蠢的,可能是由一群精神错乱的猴子设计的。”--- Linus

答案 2 :(得分:7)

有关O_DIRECT和O_SYNC的作用及其对数据完整性的影响的详细说明,请参阅此文章:

https://lwn.net/Articles/457667/

答案 3 :(得分:0)

AFAIK,O_DIRECT绕过页面缓存。 O_SYNC使用页面缓存但立即同步。页面缓存在进程之间共享,因此如果有另一个正在处理同一文件而没有O_DIRECT标志的进程可以读取正确的数据。