sockets - 同步 I/O 会使线程忙碌吗?

标签 sockets linux-kernel posix

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

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

更新:

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

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

最佳答案

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

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

因此,为了回答您的后续问题,一般来说,内核端没有单独的内核线程处理套接字 I/O,工作是由 NIC 硬件在中断上下文中完成的。

对于异步 I/O,或者更确切地说,非阻塞 I/O,唯一的区别是如何完成从用户应用程序缓冲区和内核缓冲区的复制。对于非阻塞读取,只有内核缓冲区中准备就绪并等待的数据才会复制到用户空间(这可能会导致短读取),或者如果没有数据准备好,则 read() 调用会立即返回 EAGAIN。类似地,对于非阻塞 write(),它仅复制内核缓冲区中可用空间那么多的数据,这可能会导致短写入,或者如果根本没有可用空间,则返回 EAGAIN。对于阻塞 read(),如果没有可用数据,则调用将阻塞,直到有数据为止;而对于阻塞 write(),如果内核缓冲区已满,则调用将阻塞,直到有可用空间为止。

关于sockets - 同步 I/O 会使线程忙碌吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56469471/

相关文章:

java - netty中如何在断开连接后自动连接到TCP服务器

linux-kernel - x86 上 linux 的段定义

bash - lxdialog和kconfig(menuconfig)如何协同工作?

linux - 我需要跟踪 Linux(或 POSIX 系统)中给定进程创建的所有子进程

c - sem_unlink 权限被拒绝

windows - 如何关闭 Windows 机器上的套接字?

c++ - 使用 QTcpSocket 发送字节

sockets - 如何更改nginx proxy_pass中的request_uri?

动态lib(.so)版本的兼容性

c++ - 使用 sendfile()/fcopyfile() 从共享内存映射对象复制数据