Linux磁盘文件AIO

10
根据这篇教程,在Linux上可以很容易地使用AIO实现异步磁盘文件I/O,至少从编程/API的角度来看是这样的。但在阅读了这篇教程之前和之后,我读了很多帖子和文章,有些说这是不可能做到的,或者你应该使用具有补丁的libevent以及其他问题。另外一件事是我应该等待信号的循环,但根据这个教程,我可以使用回调机制,这显然使AIO更容易使用。

现在,我甚至不算是一个Linux程序员,我只想找到一种简单的方法,在Linux上支持异步磁盘文件I/O,学习并将其添加到我需要进行个人项目的异步磁盘I/O库中。目前,我在Windows上使用重叠I/O,在非Windows平台上使用I/O工作线程。由于多线程解决方案可能会很棘手,因此我想在Linux上使用AIO来替换它。

那么,按照这篇教程描述的方式使用AIO有什么问题吗?是性能问题吗?使用AIO操作的限制是什么?

p.s. 我不在意代码是否可移植到其他符合POSIX标准的平台,只要它能在主要的Linux发行版上工作。我关心的只是常规的磁盘文件I/O。

谢谢。


4
目前Linux上的AIO支持很差。目前,AIO将绕过缓存直接执行磁盘IO,这可能会严重影响性能。 - lvella
比 worker-threads 解决方案更糟糕吗? - p00ya00
1
这取决于您的使用方式。如果您只是顺序读写一个大文件,它会表现得很好,但如果您随机访问小块,它肯定会更差。顺便说一下,如果您使用POSIX接口aio_read()等,则会得到这个工作线程解决方案。它是由glibc在用户空间上使用阻塞线程实现的。 - lvella
请参考:https://dev59.com/EG035IYBdhLWcg3wBLbb - lvella
1
我认为它的表现与POSIX AIO / glibc相同,并且比Linux本地AIO更好(其接口由libaio提供,具有诸如io_setup()等函数)。 - lvella
显示剩余2条评论
2个回答

14
本教程概述了异步 I/O 的一般情况,介绍了内核对其的支持。随后讨论了 POSIX AIO(异步 I/O 标准化 API),暗示使用在 Linux 上的 POSIX AIO API 将为您提供对内核异步 I/O 支持的访问。但事实并非如此。
在 Linux 上,有两个独立的 AIO 实现
1.内核 AIO 使用 io_submit() 等方法,仅在内核 2.6(或实际上是 2.5,可能会有向 2.4 后移植版本)上受到支持。 2.POSIX AIO 是一个 glibc 特性,与内核基本无关。它利用用户级线程进行阻塞磁盘 I/O 调用来实现 posix API。
因此,简而言之,如果您已经拥有多线程磁盘 I/O 的通用实现,最好使用它,而不是使用 glibc 的实现(因为您可能会对其具有稍微更多的控制权)。
如果您打算真正使用 io_submit() 函数族,则可能必须做很多工作才能规避这些函数的限制。
内核 AIO 要求使用 O_DIRECT 打开您的文件,这反过来要求所有文件偏移量、读写大小都与磁盘块对齐。如果只使用一个大文件,这通常不是问题,并且您可以使其与操作系统中的页缓存非常相似。但是,对于任意偏移量和长度的文件进行读写时会变得混乱。
如果您最终尝试使用内核 AIO,请强烈建议将一个或多个 eventfd 与您的 iocbs 相关联,以便您可以使用 epoll/select 等待完成,而不必在 io_getevents() 中阻塞。

3
Linux实现的POSIX AIO会为每一个写操作生成一个线程。这通常不是一个好的选择,你最好使用自己的工作线程来执行写操作,以便你能够控制参与执行的线程数。换句话说,保持现状,AIO不会带来任何好处。

2
内核AIO不会这样做,但它不太有用,因为它绕过了缓存等(当然,这就是数据库想要的)。 - MarkR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接