在最低(或者至少是值得关注的最低)硬件级别上,现代操作系统中的异步操作确实是异步的。
例如,当你从磁盘读取文件时,操作系统会将你的read
调用转换为一系列磁盘操作(跳转到位置,读取块X到Y等)。在大多数现代操作系统上,这些命令被写入特殊寄存器或主内存的特殊位置,并且磁盘控制器被告知有待处理的操作。然后,操作系统继续进行其业务,并且当磁盘控制器完成分配给它的所有操作时,它会触发一个中断,使请求读取的线程可以继续执行。
无论您正在查看何种类型的低级异步操作(磁盘I / O,网络I / O,鼠标和键盘输入等),最终都会在某个阶段向硬件发送命令,并且“回调”直到硬件到达并通知操作系统已经完成(通常以中断的形式)才会执行。
这并不是说没有一些使用轮询实现的异步操作。实现任何阻塞操作的一种微不足道(但是天真且代价高昂)的异步方式只是生成一个等待操作完成的线程(可能在紧密循环中进行轮询),然后在完成后调用回调。不过,一般来说,在操作系统级别常见的异步操作是真正的异步。
还值得提到的是,仅因为API是阻塞的并不意味着它是轮询的:你可以将阻塞API放在异步操作上,将非阻塞API放在同步操作上。例如,使用select
和kqueues等内容,线程实际上只是休眠直到出现有趣的事情。这“有趣的事情”通常以中断的形式出现,被视为操作系统应该唤醒相关线程以继续工作的指示。它不会坐在那里进行紧密的轮询等待发生某些事情。
从API上看,无法确定一个系统是否使用轮询或者“真正”的回调(例如中断),但是确实有一些异步API是真正基于异步操作的。