Five I/O modes:
[1] blocking I/O
[2] non-blocking I/O
[3] I/O multiplexing
[4] signal-driven I/O (sigio)
[5] asynchronous I/O
Generally, there are two steps for a program to input data:
1. Wait for data to be read
2. Copy data from the system kernel to the data zone of the program.
For a socket input operation, the first step is to wait for the data to be uploaded from the network to the local device. When the data packet arrives, the data will be copied from the network layer to the kernel cache. The second step is to copy the data from the kernel to the data zone of the program.
Blocking I/O mode
Blocking I/O mode is the most common I/O mode. Most programs use blocking I/O. Default
The mode in which a socket is established is the blocking I/O mode.
.
For a UDP socket
The data readiness mark is relatively simple:
(1) The entire datagram has been received.
(2) No.
The concept of TCP is complicated, and some other variables need to be appended.
In Figure 6-4, a process calls recvfrom and then the system does not return a message indicating that a datagram has arrived at the local system. Then, the system copies the data to the cache of the process. (If a system call receives an interruption signal, its call will be interrupted)
We say that this process is blocked during the call of recvfrom until the return from recvfrom.
When recvfrom returns normally, our process continues its operations.
Non-blocking mode I/O
When we set a socket to non-blocking mode, we will tell the system kernel: "When I/O operations requested by me cannot be completed immediately, if you want my process to wait for sleep, do not do this. Please immediately return an error to me."
We started to call recvfrom three times. because the system has not received network data, the kernel immediately returns an ewouldblock
. The fourth time we call the recvfrom function, a datagram has arrived, the kernel copies it to the buffer of our application, and then recvfrom returns normally, we can receive
The data to be processed.
When an application uses a non-blocking socket, it needs to use a loop to test whether a file descriptor has data readable (called polling ). Applications constantly polling the kernel to check whether I/O operations are ready. This is a waste of CPU resources.
. This mode is not very common.
I/O multiplexing
When I/O multiplexing technology is used, we call the select () function and the poll () function.
Instead of blocking when calling recvfrom (or Recv.
When we call the select function, the Select function waits for the datagram socket to enter the read-ready state. When the select function returns, that is, the socket can read data. At this time, we can call the recvfrom function to copy data to our program buffer.
Compared with the blocking mode, select () and Poll () are not advanced. In blocking mode, you only need to call a function to read or send data, after the multiplexing technology is used, we need to call two functions: the select () function or the poll () function is called before real read/write.
The advanced feature of multiplexing is that it can wait for multiple file descriptors at the same time, and any of these file descriptors (socket descriptors) enters the read-ready state, select () function.
Io multiplexing is generally used in the following scenarios:
L when a client needs to process the input and output operations of multiple file descriptors at the same time (generally standard input and output and network socket ), i/O multiplexing technology will be available.
L when the program needs to perform operations on multiple sockets at the same time.
L if a TCP server program processes both the socket that is listening for network connections and the connected socket.
L if a server program uses both TCP and UDP protocols.
L if a server uses multiple services at the same time and each service may use different protocols (such as inetd
).
Signal-driven I/O mode
We can use signals to notify us when the file descriptor is ready. We call this mode the signal-driven I/O mode.
To use a signal to drive I/O operations on a socket, the following three steps are required.
(1) One and sigio signal processing function must be set.
(2) The socket owner must be set. Generally, the f_setown parameter of the fcntl function is used.
Set the owner.
(3) The socket must be allowed to use asynchronous I/O. Generally, you can call the f_setfl command of the fcntl function,
O_async is implemented by parameters.
Although it is very easy to set the socket to asynchronous I/O, the difficult part is how to determine the state of the program when the sigio signal is sent to the socket owner in the program.
1. sigio signal of UDP socket
It is very easy to use asynchronous I/O over UDP. This signal will be generated at this time:
L socket receives a data packet.
L The socket has an asynchronous error.
When we use UDP socket asynchronous I/O, we use the recvfrom () function to read the datagram data or asynchronous I/O error information.
2. sigio signal of TCP socket
Unfortunately, asynchronous I/O has almost no effect on TCP sockets. For a TCP socket, the probability of sigio signal occurrence is too high.
Therefore, the sigio signal cannot tell us exactly what happened. In TCP connections, the sigio signal will be generated at this time:
L a new connection is successfully established on a socket listening to a port.
L a disconnected request is successfully initialized.
L a disconnected request ends successfully.
L a socket channel (sending channel or receiving channel) is disabled.
L socket receives new data.
L socket sends data.
L an asynchronous I/O error occurs.
A more practical aspect of signal-driven I/O is NTP
(Network Time Protocol) server, which uses UDP. The master cycle of this server is used to receive the datagram data packet sent from the client and then send the request. For this server, it is important to record the specific time when each packet is received.
Because it will be the value returned to the client, the client will use this data to calculate the time it takes for the datagram to return on the network. Figure 6-8 shows how to create such a UDP server.
Asynchronous I/O mode
When
When we run in asynchronous I/O mode, if we want to perform the I/O operation, we only need to tell the kernel that we want to perform the I/O operation, and then the kernel will return immediately. Specific I/O
And data copying are all done by the kernel, and our program can continue to run down. After the kernel completes all I/O operations and data copying, the kernel will notify our program.
The differences between asynchronous I/O and signal-driven I/O are:
L in signal-driven I/O mode, the kernel notifies our application to send sigio messages when operations can be performed.
L in asynchronous I/O mode, the kernel will notify our applications after all operations have been completed by the kernel.
Comparison of several I/O Modes