缓冲在Linux上的asynchronous文件I / O

我正在寻找在Linux上执行asynchronous文件I / O的最有效方法。

POSIX glibc实现使用userland中的线程。

本地aio内核API只适用于没有缓冲的操作,为内核添加对缓冲操作的支持的补丁存在,但是那些大于3岁,似乎没有人关心将它们集成到主线。

我发现了很多其他的想法,概念,补丁,可以允许asynchronousI / O,尽pipe其中大部分都是3年以上的文章。 这些在今天的内核中真的有用吗? 我已经阅读了关于servlet,acalls,内核线程的东西以及更多我现在甚至不记得的东西。

什么是在今天的内核做缓冲asynchronous文件input/输出的最有效的方法是什么?

除非你想写自己的IO线程池,否则glibc实现是一个可以接受的解决方案。 对于完全在用户空间中运行的东西,它确实工作得非常好。

根据我的经验,内核实现根本不适用于缓冲IO(尽管我看到其他人说的相反)。 如果你想通过DMA读取大量的数据,这是好的,但是如果你打算利用缓冲区缓存,它当然会占用大量的时间。
另请注意,内核AIO调用可能实际上被阻塞。 有一个有限的大小的命令缓冲区,大的读取被分解成几个较小的。 一旦队列已满,异步命令将同步运行。 惊喜。 一两年前我遇到过这个问题,找不到解释。 问周围给了我“是的,当然,这是如何工作的”答案。
从我所了解的情况来看,支持缓冲的aio的“官方”兴趣也不是很高,尽管好几年来似乎都有可用的解决方案。 我读过的一些论点是“你不想使用缓冲区”和“没有人需要这个”,“大多数人甚至不使用epoll”。 所以,呃…呃。

能够得到一个完成异步操作信号的epoll是另一个问题,直到最近,但同时这通过eventfd真的很好。

请注意,glibc实现实际上会在__aio_enqueue_request按需生成线程。 这可能没有什么大不了的,因为产卵线不再非常昂贵的,但是应该意识到这一点。 如果你对开始一个异步操作的理解是“立即返回”,那么这个假设可能不是真的,因为它可能首先产生一些线程。

编辑
作为旁注,在Windows下,存在与glibc AIO实现非常类似的情况,其中对异步操作进行排队的“立即返回”假设是不正确的。
如果您想要读取的所有数据都在缓冲区缓存中,则Windows将决定它将同步运行请求,因为它将立即完成。 这是有据可查的,而且听起来也很棒。 除了有几兆字节的情况下复制,或者如果另一个线程有页面错误或IO并发(因此竞争锁定)“立即”可能是一个惊人的长时间 – 我已经看到“立即”2 -5毫秒。 在大多数情况下,这是没有问题的,但是例如在16.66ms帧时间的限制下,你可能不希望在随机时间阻塞5ms。 因此,天真的假设“可以做从我的渲染线程异步IO没有问题,因为异步不阻止”是有缺陷的。

材料看起来很老 – 好吧,它旧的 – 因为它已经存在了很长时间,虽然不是微不足道的,但它是很好理解的。 您可以解除的解决方案发表在W.理查德·史蒂文斯的伟大和无与伦比的书(读“圣经”)。 这本书是清晰,简洁,完整的珍贵宝藏:每一页都给出了实实在在的价值:

UNIX环境下的高级编程

另外两个这样的,也是Stevens,是他的Unix Network Programming集合的前两卷:

第1卷:套接字网络API (Fenner和Rudoff)
第2卷:进程间通信

我无法想象没有这三本基础书籍。 当我找到一个没有听说过他们的人的时候,我很沮丧。

还有更多的史蒂文的书,同样珍贵:

TCP / IP画报,卷。 1:协议

我不认为Linux内核实现异步文件I / O是真的可用,除非你也使用O_DIRECT,对不起。

这里有更多有关当前世界状况的信息: http : //code.google.com/p/kernel/wiki/AIOUserGuide 。 它由Google员工在2012年更新。