为什么 select(2) 被称为 "synchronous" 多路复用?

Why is select(2) called "synchronous" multiplexing?

目前我对 select(2) 有点困惑,摘要中指出:

select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing

据我所知,许多库和程序(例如 libuv 和 nodejs)使用 select/epoll/kqueue/iocp 作为它们的事件循环,用于它们相应的 async/await 功能(以及异步 I/O?).

那么,同步多路复用到底是什么意思呢?我可以使用 select 实现异步 I/O 吗? 同步多路复用异步多路复用到底有什么区别?

你那里有一个解析错误。不是同步复用而是同步I/O的复用:select用于复用同步I/O调用。 readwrite 等被称为同步 I/O 因为它们要么阻塞直到传输完成,要么不进行传输(例如非阻塞非就绪套接字)。

这可以与真正的异步调用形成对比,在真正的异步调用中,系统调用仅启动传输并在后台完成并在完成后发出通知。

nodejs 和 libuv 是不同的野兽。尽管 C 中的 I/O 可能是多路复用和同步的,但它对 它们 将显示为异步 - 没有阻塞同步读取调用,因为这一切都透明地发生在 C/library边。

So, what exactly does synchronous multiplexing mean?

同步操作与异步操作的区别在于,前者不允许调用者继续,直到它们完成,而后者允许。 软件 (a)同步性与多线程密切相关,select()使其操作同步而不是异步的主要特点是它完全在单个(用户)内工作执行线程。当您调用 select() 时,您的线程会阻塞,直到您指定的文件描述符之一准备就绪,或者您指定的超时到期。

替代方案是一种编程模型,您可以在其中注册对文件描述符 I/O 的兴趣,然后稍后回来检查它们是否准备就绪。

然而,应该注意的是,虽然 select() 本身肯定是同步的,但多路复用主要取决于程序员。 select() 提供了实现它的方法,但 I/O 本身不执行。重要的优点在于为您提供所需的信息,以避免阻止尝试对一个文件描述符执行 I/O,而另一个文件描述符已准备好接受服务。

Can I achieve async I/O using select?

不,select 没有做任何特别促进异步的事情 I/O。它可以帮助您通过单个线程有效地处理多个 I/O 通道,但该线程是同步运行的。尽管如此,这往往是一个巨大的胜利,因为 I/O 非常慢,而且这种缓慢主要与 I/O 外围设备和媒体相关,而不是 CPU 和内存。一般来说,一个线程有足够的处理能力来处理多个 I/O 通道,只要它在任何给定的机会明智地选择要处理的通道,并且 select() 促进了这一点。