代码之家  ›  专栏  ›  技术社区  ›  Glyph

POSIX异步I/O(AIO)的状态是什么?

  •  90
  • Glyph  · 技术社区  · 16 年前

    Web上散布着一些页面,它们以不同的详细程度描述POSIX AIO工具。它们都不是最近的。不清楚他们在描述什么。例如,“官方”(?) web site for Linux kernel asynchronous I/O support here 说套接字不起作用,但我的Ubuntu8.04.1工作站上的“aio.h”手册页似乎都暗示它适用于任意文件描述符。然后有 another project that seems to work at the library layer 文档更少。

    我想知道:

    • posix aio的目的是什么?考虑到我能找到的最明显的一个实现示例说它不支持套接字,我觉得整个过程都很奇怪。它只是用于异步磁盘I/O吗?如果是,为什么要使用超通用API?如果不是,为什么磁盘I/O是第一个受到攻击的东西?
    • 哪里有例子 完成 我可以看的POSIX AIO程序?
    • 有人真的用过吗?
    • 哪些平台支持POSIX AIO?他们支持它的哪些部分?有人真的支持暗含的“对任何fd的任何I/O”吗? <aio.h> 似乎是承诺?

    对我来说,其他的复用机制都是非常好的,但是到处漂浮的随机信息片段让我好奇。

    4 回复  |  直到 16 年前
        1
  •  24
  •   Zan Lynx    16 年前

    网络I/O不是AIO的优先级,因为编写POSIX网络服务器的每个人都使用基于事件的非阻塞方法。旧的Java“数十亿阻塞线程”进退维谷。

    磁盘写入I/O已经被缓冲,磁盘读取I/O可以使用posix_fadvise之类的函数预取到缓冲区中。这使得直接的、无缓冲的磁盘I/O成为AIO唯一有用的用途。

    直接的、无缓冲的I/O只对事务性数据库非常有用,而这些数据库往往编写自己的线程或进程来管理其磁盘I/O。

    所以,在最后,让posix aio处于不服务的位置 任何 有用的目的。不要使用它。

        2
  •  68
  •   Arvid    9 年前

    利用Kqueue、EPoll、IO完成端口等技术,有效地实现了套接字I/O。异步文件I/O有点晚了(除了Windows对POSIX AIO的重叠I/O和Solaris早期支持之外)。

    如果您想做套接字I/O,最好使用上面的机制之一。

    因此,AIO的主要目的是解决异步磁盘I/O的问题。这很可能就是为什么Mac OS X只支持常规文件的AIO,而不支持套接字的原因(因为Kqueue可以更好地实现这一点)。

    写操作通常由内核缓存,并在稍后刷新。例如,当驱动器的读取头恰好经过要写入块的位置时。

    但是,对于读操作,如果您希望内核对读操作进行优先级排序和排序,那么AIO实际上是唯一的选择。这就是为什么内核(理论上)比任何用户级应用程序都能做到这一点:

    • 内核可以看到所有的磁盘I/O,而不仅仅是您的应用程序磁盘作业,并且可以在全局级别对它们进行排序。
    • 内核(可能)知道磁盘读取头在哪里,并且可以选择您以最佳顺序传递给它的读取作业,以将读取头移动到最短的距离。
    • 内核可以利用 native command queuing 进一步优化您的读取操作
    • 与readv()相比,使用lio_listio()可以对每个系统调用发出更多的读取操作,尤其是在读取不是(逻辑上)连续的情况下,这样可以节省一点系统调用开销。
    • 使用AIO,您的程序可能会稍微简单一些,因为您不需要额外的线程来阻塞读或写调用。

    也就是说,posix aio有一个非常笨拙的接口,例如:

    • 唯一有效且得到良好支持的事件回调平均值是via signals,这使得在库中很难使用,因为它意味着使用来自进程全局信号名称空间的信号号。如果您的操作系统不支持实时信号,这也意味着您必须循环处理所有未完成的请求,以确定实际完成的请求(例如,Mac OS X就是这样,而不是Linux)。在多线程环境中捕捉信号也会造成一些棘手的限制。通常,您不能对信号处理程序内的事件做出反应,但您必须发出信号,写入管道或使用signalfd()(在Linux上)。
    • lio_suspend()与select()有相同的问题,它不能很好地扩展作业的数量。
    • lio_listio()实现后,可以传递的作业数量相当有限,以可移植的方式找到这个限制并不容易。您必须调用sysconf(_sc_aio_listio_max),这可能会失败,在这种情况下,您可以使用aio_listio_max define,这不一定是定义的,但是您可以使用2,这是定义为保证被支持。

    至于使用posix aio的真实应用程序,您可以查看lighttpd(lighty),它还发布了 performance measurement 在引入支持时。

    到目前为止,大多数POSIX平台都支持POSIX AIO(Linux、BSD、Solaris、AIX、Tru64)。Windows通过其重叠的文件I/O来支持它。我的理解是,只有Solaris、Windows和Linux才真正支持异步。文件I/O一直到驱动程序,而其他OSE模拟异步。带内核线程的I/O。作为例外,Linux在glibc中的posix aio实现使用用户级线程模拟异步操作,而其本机异步I/O接口(i o_submit()等)则完全是异步的,直到驱动程序为止,假设驱动程序支持它。

    我认为在OSE中,不支持任何FD的POSIXAIO,而是将其限制在常规文件中是很常见的。

        3
  •  10
  •   starhusker    12 年前

    LibTorrent开发人员提供了一份关于以下内容的报告: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/

        4
  •  2
  •   Community rcollyer    7 年前

    在glibc中实现了aio-write;aio-read或aio-write函数的第一个调用产生了许多用户模式线程、aio-write或aio-read-post请求,线程执行pread/pwrite,当它完成后,答案将被发送回被阻塞的调用线程。

    内核级别也支持“真正的”aio(需要libaio,请参见io_submit调用) http://linux.die.net/man/2/io_submit );也需要O_Direct(可能不是所有文件系统都支持,但主要文件系统确实支持)

    请参见这里:

    http://lse.sourceforge.net/io/aio.html

    http://linux.die.net/man/2/io_提交

    Difference between POSIX AIO and libaio on Linux?