同步 I/O 是否使线程忙碌?

Does Synchronous I/O keeps thread busy?

假设我正在同步 I/O 套接字上执行 I/O,它已准备好进行 readwrite 操作。这意味着无论套接字的非阻塞(SOCK_NONBLOCK)/阻塞性质如何,调用线程都不会在操作中被阻塞。但是我不清楚以下事情 -

  1. 实际转移发生在什么时候?当套接字被标记为准备读取时,数据是否已经存在于内存中,或者数据是否会在调用 read 命令时传输?是否取决于socket的家庭?
  2. 如果在read命令期间执行数据传输,是否意味着调用线程会很忙,延迟将取决于套接字硬件?

更新:

对于套接字硬件我错了,我在考虑底层的实际数据传输。我知道 Socket 不是问题,只是 OS 中的一个实体,表示适合通信的文件描述符。

跟进问题 - 这也意味着在 write 期间,调用线程将数据写入内存。是否有一个内核线程负责在套接字的另一端传输数据?如果是,那么套接字的异步 io 与同步 io 有何不同?

一般来说,您可以将套接字I/O视为一个二级缓冲系统。在你的应用程序中有缓冲区,然后是内核缓冲区。因此,当您调用 read() 时,内核会将数据从内核缓冲区复制到您的应用程序缓冲区。相应地,当您调用 write() 时,您正在将数据从应用程序缓冲区复制到内核缓冲区。

然后内核告诉 NIC 将传入数据写入内核缓冲区,并从内核缓冲区读取传出数据。这个 I/O 通常是 AFAIK DMA-driven,这意味着内核只需要告诉 NIC 要做什么,而 NIC 负责实际的数据传输。当 NIC 完成时,它将引发中断(或者对于高 IO 速率,中断被禁用并且内核改为轮询),导致接收到中断的 CPU 内核停止执行它正在执行的任何事情(用户代码,内核代码(除非中断被禁用,在这种情况下中断将被排队))并执行中断处理程序,然后处理其他需要完成的步骤。

因此,为了回答您的 follow-up 问题,通常在内核端没有单独的内核线程处理套接字 I/O,工作由 NIC 硬件和中断上下文完成。

对于异步 I/O,或者说 non-blocking I/O,唯一的区别是如何从用户应用程序缓冲区和内核缓冲区进行复制。对于 non-blocking 读取,只有准备好并在内核缓冲区中等待的数据被复制到用户 space (这可能导致读取时间短),或者如果没有数据准备好, read()立即使用 EAGAIN 调用 returns。类似地,对于 non-blocking write(),它只复制内核缓冲区中可用 space 的数据,这可能导致短写,或者如果没有 space完全可用,返回 EAGAIN。对于阻塞 read(),如果没有可用数据,调用将阻塞直到有数据为止,而对于阻塞 write(),如果内核缓冲区已满,它将阻塞直到有一些 space可用。