根据 this tutorial在 linux 上使用 AIO 可以很容易地实现异步磁盘文件 io,至少从编程/api 的角度来看是这样。但在本教程之前和之后,我阅读了很多帖子和文章,认为这要么无法完成,要么你应该使用带补丁的 libevent 和许多其他问题。另一件事是我应该等待信号的循环,但基于本教程我可以使用回调机制,这显然使 AIO 更易于使用。
现在,我不是一个 linux 程序员,即使从长远来看我只是想找到一种直接的方法来支持 linux 上的异步磁盘文件 io,学习它并将它添加到我个人需要的异步磁盘 io 库项目。目前我在 windows 上使用重叠 io,在非 windows 平台上使用 io 工作线程。由于多线程解决方案可能很棘手,我想在 Linux 上用 AIO 替换它。
那么,本教程中描述的 AIO 有什么问题?是性能吗?使用 AIO 可以完成的操作是否有限制?
附注我不在乎代码是否不能移植到其他 POSIX 兼容平台,只要它能在主要的 linux 发行版上运行。我只关心常规磁盘文件 io。
谢谢。
最佳答案
本教程总体上概述了异步 I/O,并讨论了内核如何支持它。然后它继续谈论posix AIO(这是用于访问异步I/O的标准化API),暗示在linux上使用posix AIO API,将让您获得内核对AIO的支持。事实并非如此。
在 linux 上,实际上有两个独立的 AIO 实现:
- 使用 io_submit() 等的内核 AIO)仅在内核 2.6(或真正的 2.5,并且可能有它的反向移植版本到 2.4)中受支持。
- posix AIO 是 glibc 的一个特性,本质上与内核无关。它根据用户级线程进行阻塞磁盘 I/O 调用来实现 posix API。
因此,简而言之,如果您已经拥有用于磁盘 I/O 的多线程通用实现,那么使用它可能比使用 glibc 的实现更好(因为您可能对它有更多的控制权)。
如果您致力于实际使用 io_submit() 函数系列,则可能需要做很多工作才能规避对这些函数的限制。
内核 AIO 要求您的文件使用 O_DIRECT 打开。这反过来又要求所有文件偏移量、读写大小与磁盘上的 block 对齐。如果您只使用一个大文件并且您可以使它的工作方式与操作系统中的页面缓存非常相似,这通常很好。对于以任意偏移量和长度读取和写入任意文件,它会变得困惑。
如果您最终尝试使用内核 AIO,我强烈建议您考虑将一个或多个 eventfds 绑定(bind)到您的 iocb,这样您就可以使用 epoll/select 等待完成,而不必阻塞 io_getevents()。
关于Linux 磁盘文件 AIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8513663/