An *_*Ant 7 c linux io file-io posix
直接 I/O 是复制较大文件的最高效方法,因此我想将这种功能添加到程序中。
WindowsFILE_FLAG_WRITE_THROUGH在FILE_FLAG_NO_BUFFERINGWin32 的CreateFileA(). Linux 从 2.4.10 开始,为.open()
有没有办法在 POSIX 中实现相同的可移植结果?就像 Win32 API 从 Windows XP 到 Windows 11 的工作方式一样,如果能够以一种可靠的可移植方式跨所有类 UNIX 系统进行直接 IO,那就太好了。
不,没有直接 IO 的 POSIX 标准。
截至 2023 年 1 月,至少存在两种不同的 API 和行为。Linux、FreeBSD 和显然 IBM 的 AIX 使用标志O_DIRECTto open(),而 Oracle 的 Solarisdirectio()在已打开的文件描述符上使用函数。
Linux手册页上记录了LinuxO_DIRECT对POSIXopen()函数标志的使用:open()
O_DIRECT(自 Linux 2.4.10 起)尝试最小化来自此 https://man7.org/linux/man-pages/man2/open.2.html 文件的 I/O 的缓存影响。一般来说,这会降低性能,但在特殊情况下很有用,例如https://en.wikipedia.org/wiki/QFS当应用程序进行自己的缓存时。文件 I/O 直接与用户空间缓冲区进行交互。该
O_DIRECT标志本身努力同步传输数据,但不保证该O_SYNC标志传输数据和必要的元数据。为了保证同步 I/O,除了 之外还必须使用 O_SYNCO_DIRECT。进一步讨论请参阅下面的注释。
Linux 没有明确指定直接 IO 如何与同一文件上打开的其他描述符交互,或者使用 ; 映射文件时会发生什么mmap()。也没有对直接 IO 读或写操作的任何对齐或大小限制。根据我的经验,这些都是特定于文件系统的,并且随着时间的推移一直在改进/限制越来越少,但是大多数 Linux 文件系统都需要页面对齐 IO 缓冲区,并且许多(大多数?全部?)(是吗?仍然是?)需要页面- 大小的读取或写入。
FreeBSD 遵循 Linux 模型: 将标志传递给O_DIRECTopen():
O_DIRECT可用于最小化或消除读写的缓存效应。系统将尝试避免缓存您读取或写入的数据。如果无法避免缓存数据,就会尽量减少数据对缓存的影响。如果不小心使用,使用此标志会大大降低性能。
OpenBSD 不支持直接 IO。OpenBSDopen()或OpenBSD 'fcntl()`手册页中都没有提及直接 IO 。
IBM 的 AIX似乎支持 Linux 类型O_DIRECT标志open(),但实际发布的 IBM AIX 手册页似乎并不普遍可用。
SGI 的 Irix 还支持 Linux 风格的O_DIRECT标志open():
O_DIRECT如果设置,则在满足适当的大小和对齐限制的情况下,对生成的文件描述符的所有读取和写入都将直接执行到用户程序缓冲区或从用户程序缓冲区执行。有关如何确定对齐约束的信息, 请参阅 手册条目中的
F_SETFL和命令。是 Silicon Graphics 扩展,仅在本地 EFS 和 XFS 文件系统以及远程 BDS 文件系统上受支持。F_DIOINFOfcntl(2)O_DIRECT
有趣的是,Linux 上的 XFS 文件系统起源于 SGI 的 Irix。
Solaris 使用完全不同的界面。Solaris 使用特定directio()函数在每个文件的基础上设置直接 IO:
描述
该
directio()函数向系统提供有关应用程序在访问与打开的文件描述符关联的文件中的数据时的预期行为的建议fildes。系统使用此信息来帮助优化对文件数据的访问。该directio()函数对数据上其他操作的语义没有影响,尽管它可能会影响其他操作的性能。建议参数按文件保存;最后一个调用者
directio()使用与 关联的文件为所有应用程序设置建议fildes。建议的值在 中定义
<sys/fcntl.h>。
DIRECTIO_OFF应用程序在访问文件数据时获得默认的系统行为。
当应用程序从文件中读取数据时,数据首先缓存在系统内存中,然后复制到应用程序的缓冲区中(请参阅 参考资料
read(2))。如果系统检测到应用程序正在从文件中顺序读取,系统将从文件异步“预读”到系统内存中,以便数据立即可用于下一个操作read(2)。当应用程序将数据写入文件时,数据首先缓存在系统内存中,稍后写入设备(请参阅 参考资料
write(2))。如果可能,系统write(2)通过将数据缓存在内存页中来提高操作性能。数据被复制到系统内存中,write(2)操作立即返回到应用程序。数据随后异步写入设备。如果可能,缓存的数据会“聚集”成大块,并在单个写入操作中写入设备。系统行为可能
DIRECTIO_OFF会更改,恕不另行通知。
DIRECTIO_ON系统的行为就像应用程序在不久的将来不会重用文件数据一样。换句话说,文件数据没有缓存在系统的内存页中。
read(2)如果可能,当使用和操作访问数据时,会在应用程序内存和设备之间直接读取或写入数据write(2)。当无法进行此类传输时,系统会切换回默认行为,但仅针对该操作。一般来说,当应用程序的缓冲区在两字节(短)边界上对齐、文件中的偏移量位于设备扇区边界上并且操作的大小是设备扇区的倍数时,传输是可能的。当与 关联的文件
fildes被映射时,该建议将被忽略(请参阅 参考资料mmap(2))。系统行为可能
DIRECTIO_ON会更改,恕不另行通知。
另请注意,Solaris 上的行为有所不同:如果任何进程在文件上启用了直接 IO,则访问该文件的所有进程都将通过直接 IO 执行此操作(Solaris 10+ 对直接 IO 没有对齐或大小限制,因此在直接 IO 之间切换IO 和“正常”IO 不会破坏任何东西。*)。如果文件通过 映射mmap(),则该文件上的直接 IO 将被完全禁用。
* - 这并不完全正确 - 如果您在共享模式下使用SAMFS 或 QFS 文件系统并从文件系统的活动元数据控制器访问数据(其中文件系统必须按设计使用 Solarisforcedirectio安装选项安装,因此所有访问都通过直接完成)集群中该系统上的 IO),如果使用 禁用文件的直接 IO directio( fd, DIRECTIO_OFF ),则会损坏文件系统。如果您在 QFS 元数据控制器上进行数据库恢复,Oracle 自己的高端 RAC 数据库就会执行此操作,并且最终会出现损坏的文件系统。
| 归档时间: |
|
| 查看次数: |
973 次 |
| 最近记录: |