一尘不染

在Linux上缓冲的异步文件I / O

linux

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

POSIX glibc实现使用用户空间中的线程。

本地aio内核api仅适用于无缓冲操作,存在用于内核以添加对缓冲操作的支持的补丁程序,但是这些补丁程序已有3年的历史了,似乎没有人关心将它们集成到主线中。

我发现了许多其他允许异步I /
O的想法,概念和补丁,尽管其中大多数都在3年以上的文章中。在当今的内核中,这到底是什么呢?我已经阅读了有关servlet,调用,内核线程的内容以及我什至不记得的更多内容。

在当今的内核中执行缓冲异步文件输入/输出的最有效方法是什么?


阅读 269

收藏
2020-06-07

共1个答案

一尘不染

除非您想编写自己的IO线程池,否则glibc实现是可以接受的解决方案。实际上,对于完全在用户区中运行的某些东西,它实际上出奇地好。

根据我的经验,内核实现根本无法与缓冲IO一起使用(尽管我已经看到其他人说的相反!)。如果您想通过DMA读取大量数据,那很好,但是如果您打算利用缓冲区高速缓存,那当然会浪费很多时间。
另请注意,内核AIO调用实际上可能会阻塞。由于命令缓冲区的大小有限,因此较大的读取将分成几个较小的读取。队列填满后,异步命令将同步运行。惊喜
我在一两年前遇到了这个问题,找不到解释。问周围的问题给了我“是的,这就是它的工作原理”的答案。
据我了解,尽管有几种可行的解决方案似乎已经问世多年,但支持缓冲aio的“官方”兴趣也不是很大。我已经读过的一些论据是“无论如何都不想使用缓冲区”,“没人需要”和“大多数人甚至还没有使用epoll”。所以,嗯。

epoll直到最近,能够通过完成的异步操作发出信号是另一个问题,但是与此同时,通过确实可以很好地工作eventfd

请注意,glibc实现实际上将按需 生成 线程__aio_enqueue_request。这可能是没什么大不了的,因为产卵线程是不是
贵的要命了,而是应该意识到这一点。如果您对启动异步操作的理解是“立即返回”,则该假设可能不正确,因为它可能首先产生了一些线程。

编辑
作为附带说明,在Windows下,存在与glibc AIO实现中的情况非常相似的情况,其中排队异步操作的“立即返回”假设不成立。
如果您要读取的所有数据都在缓冲区高速缓存中,则Windows将决定改为 同步 运行请求 __,因为无论如何它都会立即完成。
这是有据可查的,而且听起来也很棒。除非要复制几兆字节,或者另一个线程发生页面错误或同时(同时争夺锁)IO(很可能是很长的时间),我看到的“立即”时间是2
-5毫秒。在大多数情况下这没有问题,但是例如在16.66ms帧时间的约束下,您可能不想冒随机时间阻塞5ms的风险。因此,“可以从我的渲染线程进行异步IO没问题,因为异步不会阻塞”这一天真假设是有缺陷的。

2020-06-07