Linux内核AIO、开放式系统调用

15

为什么Linux内核AIO不支持异步“open”系统调用?因为“open”可能会在文件系统上阻塞很长时间,进而导致无法异步执行。


No traces of inital research. - Pavel Šimerda
1
这没有意义。即使您使用O_NONBLOCK打开,您仍需要select或某种轮询机制来查看文件是否准备好进行I/O操作。否则,您可能会简单地排队AIO R/W请求,这些请求可能永远不会成功。如果需要并发性,则可以生成另一个线程来打开文件,或继续提供其他I/O操作。 - Brett Hale
我指的是仅限于Linux内核AIO(异步)。我不需要select,epoll等。 - andreych
1
我只找到了来自Linus的非常古老的解释:http://lkml.iu.edu//hypermail/linux/kernel/0102.1/0124.html - andreych
2个回答

15

首先,这是一个完全合理和合法的问题;downvote(踩)非常不幸,它可能会把比我更有知识的人推开。

据我所知,没有一个好的原因。您发现的讨论是相关的,但并不令人满意(这也可能是您的结论)。虽然Torvald 的观点在技术上是正确的,但他们显然忽略了屏幕上的大象 - GUI编程 - 以及我确定的许多其他用例。

  • 是的,网络服务器会受到网络延迟的限制。虽然这不应该成为忽略其他IO的理由,但我可以接受。

  • 是的,许多服务器工作负载将能够利用dentry/inode缓存,但并非所有工作负载都能够利用,而且总会有缺失。

  • 是的,“购买更多RAM”的论点是有效的。但我从未认为这是一个好的论点。

  • 还有其他所有用例。对于许多用例,包括GUI编程,我们有时或经常阻塞并不重要;我们永远不应该阻塞。如果访问模式非常随机且时间间隔很长,购买更多RAM也无济于事——除非具备与二级存储所提供的容量相同的容量。

    “它应该快速”这个想法也是错误的;始终考虑远程文件系统。

唯一令人信服的观点是:

简短明了地说," aio_open()" 基本上不应该成为问题。如果出现问题,则说明您设计有误,或者您试图过于努力地将所有内容单线程化(通过仅称其为 "AIO" 而将发生的线程 "隐藏" - 简而言之,欺骗自己)。
重点在于要避免线程,因此这句话让我感到惊讶。其他参数甚至被列举出来表明它太脆弱,不能独立存在。
在同一讨论中挖掘,您可以找到 Mikulas Patocka 的这篇文章:
您可以使用像 FreeBSD 和某些商业 Unix 那样的内核线程来模拟异步 IO,但您仍需要尽可能多的(可能是内核)线程来处理您正在服务的请求。
实现真正的异步 IO 需要从头重写所有文件系统和整个 VFS。这是不可能的。

http://lkml.iu.edu//hypermail/linux/kernel/0102.1/0074.html

这听起来像是一个合适的解释,尽管显然不是一个好的解释。
请记住,这是一个旧的线程,很多事情从那时起已经发生了改变,因此这个答案的价值非常小。但是,它提供了为什么一个假设的在历史上并不可用的洞察力。此外,请理解许多内核讨论(或任何项目的任何内部讨论)通常都希望所有参与者都从一组大量的假设开始。因此,完全有可能我没有正确地看待这个问题。
话虽如此,这一点很有趣(Stephen C. Tweedie):Ahh,但即使是VMS SYS$QIO,在打开、分配IO请求包和将文件位置映射到磁盘块方面也是同步的。只有数据IO才是异步的(而Ben针对Linux的异步IO工具也提供了这一点)。

http://lkml.iu.edu//hypermail/linux/kernel/0102.1/0139.html

因为它强化了一个观念,即许多不同的系统不会异步实现“open”(和其他调用)。此外,“aio_open”未被POSIX规定,并且我找不到解释原因的讨论。Windows似乎也忽略了这个问题。
好像这个概念本身有什么问题或难点,除了最后没有人能够提出充分的理由来解释为什么。
我的猜测是这只是低优先级,一直以来都是如此。包括线程或预先打开文件在内的解决方法据说已足够满足足够的使用案例,无法证明提供功能的工作是合理的。
如果想要深入探究这个问题,我认为您需要将讨论带到更合适的渠道,例如LKML。
注:LKML是Linux内核邮件列表。

关于io_uring的附注:虽然对这些原始AIO API的兴趣有所减弱,但是本文概述了接下来发生的事情,直到io_uring出现,它仍然在当前得到广泛应用。您将在那里找到另一篇关于异步openat的讨论,尽管我还没有检查它的结果。 - tne

0

我编写了一个相当简单但功能强大的cpaio C实用程序,使用Linux本地aio+O_DIRECT(io_submit,io_getevents)复制一堆文件。我只是尽早打开文件,排队初始aio读取,并且只在打开足够的文件(或者如果文件很少,则全部打开)后才会查找读取结果。异步打开文件的方法会更好,但最终这并不重要。
我用这个工具复制了数十TB的数据。
最终,我认为没有异步打开是有道理的。这是一个复杂的操作,内核本质上必须启动一个线程来处理它。


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