系统调用如select()或poll()如何在引擎盖下工作?

时间:2012-07-15 22:09:44

标签: linux sockets asynchronous io

我知道通过select()poll()的异步I / O操作不使用处理器时间,即它不是繁忙的循环,但那么这些是如何真正实现的呢?它是否以某种方式支持硬件,为什么使用这些处理器的处理器成本不明显呢?

2 个答案:

答案 0 :(得分:16)

这取决于select / poll正在等待的内容。让我们考虑几个案例;我将假设一台单核机器进行简化。

首先,考虑select正在等待另一个进程的情况(例如,另一个进程可能正在执行某些计算,然后通过管道输出结果)。在这种情况下,内核会将您的进程标记为等待输入,因此它不会为您的进程提供任何CPU时间。当另一个进程输出数据时,内核将唤醒您的进程(在CPU上给它一些时间),以便它可以处理输入。即使其他进程仍在运行,也会发生这种情况,因为现代操作系统使用抢占式多任务,这意味着内核会定期中断进程,以便让其他进程有机会使用CPU("时间分片"。)

select等待I / O时,图片会发生变化;例如,网络数据或键盘输入。在这种情况下,虽然过时的硬件必须旋转CPU等待输入,但所有现代硬件都可以将CPU本身置于低功耗状态,等待等等。状态,直到硬件提供中断 - 内核处理的特殊处理事件。在中断处理程序中,CPU将记录传入的数据,并在从中断返回后唤醒您的进程以允许它处理数据。

答案 1 :(得分:7)

没有硬件支持。好吧,有......但没什么特别的,这取决于你在看什么样的文件描述符。如果涉及设备驱动程序,则实现取决于驱动程序和/或设备。例如,套接字。如果您等待读取某些数据,则会发生一系列事件:

  1. 某些进程调用poll()/ select()/ epoll()系统调用以等待套接字中的数据。从用户模式到内核有一个上下文切换。
  2. 当某个数据包到达时,NIC会中断处理器。驱动程序中的中断例程将数据包推送到队列后面。
  3. 有一个内核线程从该队列中获取数据并唤醒内核中的网络代码来处理该数据包。
  4. 处理数据包时,内核确定了预期的套接字,将数据保存在套接字缓冲区中,并将系统调用返回给用户空间。
  5. 这只是一个非常的简要描述,有很多细节缺失,但我认为这足以说明问题。

    另一个没有驱动程序的例子是unix套接字。如果等待其中一个数据,则等待的进程将添加到列表中。当套接字另一端的其他进程写入数据时,内核会检查该列表并再次应用第4点。

    我希望它有所帮助。我认为这些例子是最好的。