在最低(或至少是最值得关注的)硬件级别,异步操作在现代操作系统中确实是异步的。
例如,当您从磁盘读取文件时,操作系统会将您的调用转换read
为一系列磁盘操作(查找位置、读取块 X 到 Y 等)。在大多数现代操作系统上,这些命令要么写入特殊寄存器,要么写入主存储器中的特殊位置,并且通知磁盘控制器有待处理的操作。然后操作系统继续它的业务,当磁盘控制器完成分配给它的所有操作时,它会触发一个中断,导致请求读取的线程从它停止的地方开始。
无论您正在查看哪种类型的低级异步操作(磁盘 I/O、网络 I/O、鼠标和键盘输入等),最终都会有某个阶段将命令分派到硬件,并且“回调”在硬件伸出并通知操作系统它已经完成之前不会执行,通常以中断的形式。
这并不是说没有使用轮询实现的一些异步操作。异步实现任何阻塞操作的一种简单(但幼稚且昂贵)的方法是生成一个等待操作完成的线程(可能在紧密循环中轮询),然后在完成时调用回调。不过,一般来说,操作系统级别的常见异步操作是真正异步的。
还值得一提的是,API 阻塞并不意味着它是轮询:您可以将阻塞 API 放在异步操作上,将非阻塞 API 放在同步操作上。例如,对于和 kqueue 之类的东西select
,线程实际上只是进入睡眠状态,直到发生有趣的事情。那个“有趣的东西”(通常)以中断的形式出现,这表明操作系统应该唤醒相关线程以继续工作。它不只是在一个紧密的循环中等待某事发生。
确实无法仅从其 API 判断系统是使用轮询还是“真实”回调(如中断),但是确实存在真正由异步操作支持的异步 API。