像 select() 或 poll() 这样的系统调用是如何在后台工作的?

Posted

技术标签:

【中文标题】像 select() 或 poll() 这样的系统调用是如何在后台工作的?【英文标题】:How do system calls like select() or poll() work under the hood? 【发布时间】:2012-07-14 19:31:49 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

    某些进程调用 poll()/select()/epoll() 系统调用来等待套接字中的数据。有一个从用户模式到内核的上下文切换。 NIC 在某些数据包到达时中断处理器。驱动程序中的中断例程将数据包推到队列的后面。 有一个内核线程从该队列中获取数据并唤醒内核中的网络代码以处理该数据包。 处理数据包时,内核会确定期待它的套接字,将数据保存在套接字缓冲区中并将系统调用返回给用户空间。

这只是一个非常简短的描述,有很多细节缺失,但我认为这足以说明问题。

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

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

【讨论】:

【参考方案2】:

这取决于select/poll 正在等待什么。让我们考虑几个案例;为简化起见,我将假设一台单核机器。

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

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

【讨论】:

以上是关于像 select() 或 poll() 这样的系统调用是如何在后台工作的?的主要内容,如果未能解决你的问题,请参考以下文章

分析底层 Linux 操作系统函数/代码,如 select() 和 poll()?

I/O多路转接select/poll/epoll

select,poll,epoll,selectors

linux下select/poll/epoll机制的比较

UNIX网络编程笔记—I/O复用select/poll

Linux I/O复用中select poll epoll模型的介绍及其优缺点的比較