当您调用 select(2) 时,内核如何确定套接字已准备就绪?

When you call select(2) how does the kernel figure out a socket is ready?

The man page for select(2) says:

select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2) without blocking, or a sufficiently small write(2)).

在这段等待时间内,内核本身是否不断轮询套接字以查看它们是否准备就绪?监视套接字是如何实现的?

不,它在每个文件描述符的等待队列中注册,然后进入睡眠状态(直到收到信号。)。 Nelson Elhage 在 Quora 上有一个非常简洁的答案,其中包含更多信息:

https://www.quora.com/Network-Programming-How-is-select-implemented

您还可以深入研究 source

https://eklitzke.org/how-tcp-sockets-work 回答了我的问题

When a new data packet comes in on the network interface (NIC), the kernel is notified either by being interrupted by the NIC, or by polling the NIC for data. Typically whether the kernel is interrupt driven or in polling mode depends on how much network traffic is happening; when the NIC is very busy it’s more efficient for the kernel to poll, but if the NIC is not busy CPU cycles and power can be saved by using interrupts. Linux calls this technique NAPI, literally “New API”.

When the kernel gets a packet from the NIC it decodes the packet and figures out what TCP connection the packet is associated with based on the source IP, source port, destination IP, and destination port. This information is used to look up the struct sock in memory associated with that connection. Assuming the packet is in sequence, the data payload is then copied into the socket’s receive buffer. At this point the kernel will wake up any processes doing a blocking read(2), or that are using an I/O multiplexing system call like select(2) or epoll_wait(2) to wait on the socket.