所有异步I/O最终都是通过轮询实现的吗?

13

我曾经认为异步I/O总是具有回调形式。但最近我发现一些低级实现正在使用轮询式API。

  1. kqueue
  2. libpq

这使我想到,也许所有(或大多数)异步I/O(文件、套接字、Mach端口等)最终都是以某种轮询方式实现的。也许回调形式只是更高级别API的抽象。

这可能是一个愚蠢的问题,但我不知道大多数异步I/O实际上是如何在低层实现的。我只是使用了系统级通知,当我看到kqueue时——它是系统通知,它是轮询式的!

我应该如何理解低级别的异步I/O?如果实际上是这样的话,高级别的异步通知是如何从低级别的轮询系统中产生的?


如果这个问题不适合在 Stack Overflow 上发布,我可以问问有没有更好的地方可以发布这个问题吗?(例如其他的 SE 网站,如 Programmers 或 Unix & Linux ...) - eonil
有趣的问题。对于Stackoverflow格式来说不太合适,但我不会关闭投票...因为我想听听一些答案! - Floris
2
“中断”是一个非常相关的词。 - Mooing Duck
1个回答

15

在最低(或者至少是值得关注的最低)硬件级别上,现代操作系统中的异步操作确实是异步的。

例如,当你从磁盘读取文件时,操作系统会将你的read调用转换为一系列磁盘操作(跳转到位置,读取块X到Y等)。在大多数现代操作系统上,这些命令被写入特殊寄存器或主内存的特殊位置,并且磁盘控制器被告知有待处理的操作。然后,操作系统继续进行其业务,并且当磁盘控制器完成分配给它的所有操作时,它会触发一个中断,使请求读取的线程可以继续执行。

无论您正在查看何种类型的低级异步操作(磁盘I / O,网络I / O,鼠标和键盘输入等),最终都会在某个阶段向硬件发送命令,并且“回调”直到硬件到达并通知操作系统已经完成(通常以中断的形式)才会执行。

这并不是说没有一些使用轮询实现的异步操作。实现任何阻塞操作的一种微不足道(但是天真且代价高昂)的异步方式只是生成一个等待操作完成的线程(可能在紧密循环中进行轮询),然后在完成后调用回调。不过,一般来说,在操作系统级别常见的异步操作是真正的异步。

还值得提到的是,仅因为API是阻塞的并不意味着它是轮询的:你可以将阻塞API放在异步操作上,将非阻塞API放在同步操作上。例如,使用select和kqueues等内容,线程实际上只是休眠直到出现有趣的事情。这“有趣的事情”通常以中断的形式出现,被视为操作系统应该唤醒相关线程以继续工作的指示。它不会坐在那里进行紧密的轮询等待发生某些事情。

从API上看,无法确定一个系统是否使用轮询或者“真正”的回调(例如中断),但是确实有一些异步API是真正基于异步操作的。


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