Linux中POSIX AIO和libaio之间的区别是什么?

56

我所理解的是:

POSIX AIO APIs在<aio.h>中进行了原型设计,您需要使用librt(-lrt)链接您的程序,而libaio APIs在<libaio.h>中,您的程序需要链接libaio(-laio)。

我无法理解的是:

1.内核是否会以不同的方式处理这两种方法?

2.对于使用这两种方法,O_DIRECT标志是否是必需的?

正如这篇文章中提到的,当使用libaio时,在没有O_DIRECT的情况下,libaio可以正常工作。好的,我明白了,但是:

根据R.Love的Linux系统编程一书所述,Linux仅支持在使用O_DIRECT打开的常规文件上使用aio(我假设是POSIX AIO)。但是,我编写的一个小程序(aio.h,链接了-lrt),在未使用O_DIRECT标志打开的文件上调用aio_write函数时却能够无问题运行。

1个回答

76

在linux上,两种AIO实现有根本的不同。

POSIX AIO是一种用户级别的实现,它在多个线程中执行普通的阻塞式I/O操作,从而产生I/O是异步的错觉。这样做的主要原因是:

  1. 它适用于任何文件系统
  2. 它基本上适用于任何操作系统(请记住gnu的libc是可移植的)
  3. 它适用于启用缓冲的文件(即未设置O_DIRECT标志)

主要缺点是,队列深度(即实际上可以有多少未完成操作)受您选择的线程数限制,这也意味着一个磁盘上的慢操作可能会阻塞传往另一个磁盘的操作。它还会影响内核和磁盘调度程序看到的哪些I / O(或多少)。

内核AIO(即io_submit()等)是内核支持异步I / O操作的方式,其中io请求实际上在内核中排队,由任何磁盘调度程序进行排序,可能会将其中一些以异步操作(使用TCQ或NCQ)的方式转发到实际磁盘。该方法的主要限制是,并非所有文件系统都很好地或根本不支持异步I/O(可能会回退到阻塞语义),文件必须使用O_DIRECT打开,这会附带许多其他的I/O请求限制。如果您未使用O_DIRECT打开文件,则可能仍然“工作”,也就是说,您会收到正确的数据返回,但它可能并不是异步完成的,而是回退到了阻塞语义。

还请注意,在某些情况下,io_submit()实际上可能会在磁盘上阻塞。


谢谢回复。因此,对于POSIX AIO,O_DIRECT不是*必须的,但对于内核AIO,它是(为了确保没有回退发生)?这似乎与书中提到的内容相矛盾。在内核代码中,VFS具有这些aio_read/write函数,这些函数由aio_read/write系统调用调用(这是POXIS AIO而不是内核AIO)。 - itisravi
2
没有 aio_* 系统调用(http://linux.die.net/man/2/syscalls)。你在 vfs 中看到的 aio_* 函数可能是内核 aio 的一部分。用户级别的 aio_* 函数不能一一映射到系统调用。 - Arvid
1
@Arvid,您能否详细说明io_submit()在什么情况下会阻塞?(您提到有时它可能会阻塞磁盘) - ARH
2
我的理解是块设备层基本上保证不会阻塞。如果你只关心访问原始磁盘,那么没问题。然而,文件系统并没有假定有人可能想异步使用它们。我测试了ext4、reiser和xfs。如果我没记错,ext4是最容易阻塞的,但也是完成我的基准测试最快的。在linux-aio邮件列表中搜索会给你很多结果。这是我的链接:http://article.gmane.org/gmane.linux.kernel.aio.general/3024/match=blocking+io_submit - Arvid
1
这里有一份非详尽列表,列出了导致io_submit()阻塞的因素,请参考https://dev59.com/E1sW5IYBdhLWcg3wyZ0w#46377629 - Anon

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