Linux上的AIO支持

AIO support on Linux

本文关键字:支持 AIO 上的 Linux      更新时间:2023-10-16

谁知道我在哪里可以得到最新的Linux内核对aio的支持状态的最新信息?谷歌搜索带来的网页可能已经完全过时了。

编辑:

更具体地说,我对管道和套接字等与文件无关的描述符感兴趣。网上的东西表明没有支持,情况仍然是这样吗?

Edit2:我正在寻找的是类似于Windows OVERLAPPED IO

你不需要POSIX AIO(即man AIO)异步使用套接字和管道。根据man 3 aio,这甚至是不可能的。您应该使用非阻塞文件描述符,以及事件通知接口,例如select()poll()epollepoll是特定于Linux的,但比前两种可伸缩性要好得多。

要在非阻塞模式下使用文件描述符,您必须在每个文件描述符上设置O_NONBLOCK标志:

fcntl(fd, F_SETFL, O_NONBLOCK)

当文件描述符处于非阻塞模式后,像read()write()这样的I/O操作将永远不会阻塞,但如果操作不能立即完成,将返回EAGAINEWOULDBLOCK。一些更具体的操作,如connect(),必须在非阻塞模式下以不同的方式使用;参见相关手册页。

为了能够正确使用非阻塞文件描述符,您的应用程序需要是事件驱动的。基本上,在main()中,您需要首先初始化内容,然后进入事件循环。事件循环反复等待事件(使用事件通知接口,例如epoll_wait()),然后检查发生了哪些事件,并响应它们。

现在,当你说read()时,EWOULDBLOCK失败了,你把它添加到文件描述符列表中,以观察其可读性;当事件提供程序指示可读性时,再试一次。

同样,如果您尝试使用write()EWOULDBLOCK失败,则可能需要缓冲数据,并在指示可写性时再次尝试。

Linux下有两种类型的AIO

一个是kernel-AIO。它是丑陋的,有时不按照文档的行为(例如,它会在某些条件下同步运行,而你无法对它做些什么,在某些条件下它不会正确取消飞行中的请求,等等)。不能在管道上工作。
这些是io_类函数。注意,你必须链接-laio,它必须单独安装在某些系统上(例如Debian/Ubuntu)。

第二个是纯用户层实现(glibc),它根据需要生成线程来处理请求。它有很好的文档,工作得相当好,根据文档,它几乎可以处理任何文件描述符,包括管道
这些是aio_类函数。我强烈建议使用这些,即使它们是一个"不酷的用户实现"——它们工作得很好。

两者都可以同时使用eventfd作为通知机制,顺便说一句,虽然内核版本上次我看时仍然没有记录(但函数在头文件中)。

或者,正如Ambroz Bizjak指出的那样,完全跳过AIO,因为你所描述的并不是严格必要的。

编辑:


另一方面,既然您使用了"管道"answers"套接字",那么您知道vmsplice和splice吗?这些可能是向套接字/管道发送数据的最有效的函数。不幸的是,它是另一个文档含糊不清、难以理解的带有模糊陷阱的黑客。我已警告过你,请自担风险。

splice允许您将数据从套接字(或任何文件描述符)传输到管道,或者其他方式。vmsplice允许你在应用空间和管道之间传输数据。
具有讽刺意味的是,理想情况下,vmsplice应该做完全相同的事情(重新映射页面,又名。"玩VM"),早在2006年,一个特别的人就用它来声称所有的BSD开发人员都是白痴。

好消息到此为止,坏消息是你可以移动的数据量有一个"秘密限制"。据我所知,它是64kB(但可在/proc中某处配置)。如果你有更多的数据,那么你必须在几个块中工作,可能有几个管道缓冲区,在读取一个时填充另一个,并在它们完成后重用旧的管道缓冲区。
这就是问题变得复杂的地方。如果你浏览内核陷阱的讨论,你会发现即使是大师也不能100%确定在处理多个缓冲区时,什么时候重写旧缓冲区是安全的。

此外,对于vmsplice 真正工作(即重新映射页面而不是复制),您需要使用"GIFT"标志,至少对我来说,从文档中不清楚内存变成了什么。按照文档的要求,您将需要泄漏内存,因为您永远不允许再次接触它。当然不可能是这样。也许我只是笨。

我最终放弃了这一点,只是解决了使用epoll的准备和非阻塞套接字与普通普通write。这种组合可能不是最好的表现,但是它有良好的文档,并且像文档一样工作。

AIO支持已经包含在linux内核中。这就是为什么Google上的第一个热门版本只提供针对2.4 Linux内核的补丁。在2.6和3.0中,它已经存在了。

如果您检查Linux内核源代码,它位于fs/aio.c

GNU libc手册中有一些文档,但请注意aio并不适用于所有类型的Linux文件描述符。大多数通用的"如何"文档的日期都在2006年左右,这是合适的,因为那是Linux中的AIO成为头条新闻的时候。

请注意POSIX.1b和Unix98标准没有改变,所以您可以具体说明示例"过时"的性质吗?