I/O Multiplexing
「定义」What we need is the capability to tell the kernel that we want to be notified if one or more I/O conditions are ready (i.e., input is ready to be read, or the descriptor is capable of taking more output). This capability is called I/O multiplexing and is provided by the select
and poll
functions.
i/o多路复用的使用场景:
- When a client is handling multiple descriptors (normally interactive input and a network socket), I/O multiplexing should be used.
- It is possible, but rare, for a client to handle multiple sockets at the same time.
- If a TCP server handles both a listening socket and its connected sockets, I/O multiplexing is normally used.
- If a server handles both TCP and UDP, I/O multiplexing is normally used.
- If a server handles multiple services and perhaps multiple protocols (e.g., the
inetd
daemon), I/O multiplexing is normally used.
I/O Models
The five I/O models that are available to us under Unix:
- blocking I/O
- nonblocking I/O
- I/O multiplexing (
select
andpoll
) - signal driven I/O (
SIGIO
) - asynchronous I/O (the POSIX
aio_
functions)
There are normally two distinct phases for an input operation:
- Waiting for the data to be ready
- Copying the data from the kernel to the process
For an input operation on a socket, the first step normally involves waiting for data to arrive on the network. When the packet arrives, it is copied into a buffer within the kernel. The second step is copying this data from the kernel’s buffer into our application buffer.
Blocking I/O Model
By default, all sockets are blocking.
In Figure 6.1, the process calls recvfrom
and the system call does not return until the datagram arrives and is copied into our application buffer, or an error occurs. The most common error is the system call being interrupted by a signal, as we described in Section 5.9. We say that our process is blocked the entire time from when it calls recvfrom until it returns. When recvfrom
returns successfully, our application processes the datagram.
Nonblocking I/O Model
When we set a socket to be nonblocking, we are telling the kernel ‘‘when an I/O operation that I request cannot be completed without putting the process to sleep, do not put the process to sleep, but return an error instead.’’
The first three times that we call recvfrom
, there is no data to return, so the kernel immediately returns an error of EWOULDBLOCK
instead. The fourth time we call
recvfrom
, a datagram is ready, it is copied into our application buffer, and recvfrom
returns successfully. We then process the data.
When an application sits in a loop calling recvfrom
on a nonblocking descriptor like this, it is called polling. The application is continually polling the kernel to see if some operation is ready. This is often a waste of CPU time, but this model is occasionally encountered, normally on systems dedicated to one function.
I/O Multiplexing Model
With I/O multiplexing, we call select
or poll
and block in one of these two system calls, instead of blocking in the actual I/O system call. 「实际上是将阻塞的那次call转移到了select
和poll
.」
We block in a call to select
, waiting for the datagram socket to be readable. When select returns that the socket is readable, we then call recvfrom
to copy the datagram into our application buffer.
Signal-Driven I/O Model
Refer to UNP chapter 6.2.
Asynchronous I/O Model
In general, these functions work by telling the kernel to start the operation and to notify us when the entire operation (including the copy of the data from the kernel to our buffer) is complete.
This system call returns immediately and our process is not blocked while waiting for the I/O to complete.
Synchronous I/O versus Asynchronous I/O
POSIX defines these two terms as follows: • A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes. • An asynchronous I/O operation does not cause the requesting process to be blocked.
Using these definitions, the first four I/O models—blocking, nonblocking, I/O multiplexing, and signal-driven I/O—are all synchronous because the actual I/O operation (recvfrom
) blocks the process. Only the asynchronous I/O model matches the asynchronous I/O definition.
Asio doc says:
- Synchronous operations are functions that do not return control to the caller until the corresponding operating system operation completes.
- Asynchronous operations do not block the caller, but instead involve the delivery of a notification to the program when the corresponding operating system operation completes.
see also 同步异步阻塞非阻塞
- IO 多路复用是什么意思? - 罗志宇的回答 - 知乎
- https://zhuanlan.zhihu.com/p/272891398
- https://segmentfault.com/a/1190000003063859
- https://jvns.ca/blog/2017/06/03/async-io-on-linux—select—poll—and-epoll/
- https://daniel.haxx.se/docs/poll-vs-select.html
References
- Unix Network Programming, chater 6