2

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

编辑:

更具体地说,我对管道和套接字等非文件相关的描述符感兴趣。网上的东西都说不支持,现在还是这样吗?

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

4

3 回答 3

5

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

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

fcntl(fd, F_SETFL, O_NONBLOCK)

在文件描述符处于非阻塞模式后,I/O 操作就像read()并且write()永远不会阻塞,但会返回EAGAIN或者EWOULDBLOCK如果操作不能立即完成。一些更具体的操作,比如connect(),必须在非阻塞模式下以不同的方式使用;请参阅相关手册页。

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

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

类似地,如果您尝试write()但它失败并显示EWOULDBLOCK,您可能希望缓冲数据并在指示可写性时重试。

于 2011-10-31T17:58:46.727 回答
3

Linux下有两种AIO。

一种是内核-AIO。它很丑陋,有时不符合文档的要求(例如,它会在某些条件下同步运行而您无法对其做任何事情,并且在某些条件下它不会正确取消正在进行的请求等, ETC)。它不适用于管道。
这些是io_函数的种类。请注意,您必须与 链接-laio,您必须在某些系统(例如 Debian/Ubuntu)上单独安装它。

第二个是纯用户态实现(glibc),它按需产生线程来处理请求。它有据可查,工作得相当好,并且根据文档,它几乎可以与任何文件描述符一起使用,包括管道
这些是aio_函数的种类。我肯定会推荐使用这些,即使它们是“不酷的用户空间实现”——它们工作得很好。

同时,两者都使用 eventfd 作为通知机制,顺便说一句,尽管我上次查看时内核版本仍未记录(但功能在标题中)。

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

EDIT:
On a different note, since you used the words "pipes" and "sockets", are you aware of vmsplice and splice? Those are the probably most efficient functions to send data to/from sockets/pipes. Unluckily, it's another one of those ambiguously documented, hard to understand hacks with obscure pitfalls. Proceed at your own risk, you have been warned.

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

好消息就这么多,坏消息是你可以移动多少数据有一个“秘密限制”。据我记得它是 64kB(但可在 /proc 中的某处配置)。如果你有比这更多的数据,你必须在几个块中工作,大概有几个管道缓冲区,在读取另一个时填充一个,并在完成后重用旧的管道缓冲区。
这就是复杂的地方。如果您浏览讨论 Kernel Trap,您会发现即使是大师也不能 100% 确定在处理多个缓冲区时覆盖旧缓冲区何时是安全的。

Also, for vmsplice to really work (i.e. remapping pages instead of copying), you need to use the "GIFT" flag, and at least to me it's not clear from the docs what becomes of that memory then. Following the docs to the letter, you would need to leak memory, since you are never allowed to touch it again. Of course that can't be it. Maybe I'm just stupid.

I eventually gave up on this, and just settled for using epoll for readiness and non-blocking sockets with plain normal write. That combination is maybe not the utmost performer, but it is well-documented and works as documented.

于 2011-10-31T18:02:52.607 回答
2

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

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

GNU libc 手册中有一些文档,但请注意,并非所有类型的 Linux 文件描述符都可以使用 aio。大多数一般的“操作方法”文档都是在 2006 年左右发布的,这是合适的,因为那是 Linux 中的 AIO 成为头条新闻的时候。

请注意,POSIX.1b 和 Unix98 标准没有改变,那么您能否具体说明一下示例“过时”的性质?

于 2011-10-31T17:04:08.273 回答