Io open(2)中的O_SYNC和O_DIRECT标志有何不同/相似?

Io open(2)中的O_SYNC和O_DIRECT标志有何不同/相似?,io,posix,synchronous,Io,Posix,Synchronous,O_SYNC和O_DIRECT标志的使用和效果非常混乱,并且在不同平台之间似乎有所不同。从Linux手册页(参见示例),O_DIRECT提供同步I/O,最小化缓存影响,并要求您自己处理块大小对齐。O_SYNC只保证同步I/O。虽然两者都保证数据写入硬盘缓存,但我认为直接I/O操作应该比普通同步I/O更快,因为它们绕过了页面缓存(尽管FreeBSD的open手册页(2)指出使用O_SYNC时会绕过缓存。请参阅) O_DIRECT和O_SYNC标志之间的具体区别是什么?一些实现建议使用O|u SYN

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


O_DIRECT和O_SYNC标志之间的具体区别是什么?一些实现建议使用O|u SYNC | O|u DIRECT。为什么?

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

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

O_SYNC保证在所有数据传输到磁盘之前(据操作系统所知),呼叫不会返回。这仍然不能保证数据不在硬盘写缓存中的某个位置,但这是操作系统所能保证的


O|u DIRECT O|u SYNC是这些的组合,即“DMA+保证”。

实际上,在linux 2.6下,O|u DIRECT是同步的,请参见手册页:

在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操作

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

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

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

在内核版本2.4.10的Linux下添加了O_直接支持。较旧的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_直接I/O没有对齐限制

总之,O_DIRECT是一个潜在的强大工具,应谨慎使用。建议这样做