Five I/O modes-blocking (default IO mode), non-blocking (common language pipeline), I/O multiplexing (IO multiplexing scenario), signal I/O, asynchronous I/O
Five I/O modes:
"1" Blocking I/O (I/O operations under Linux are blocking I/O by default, that is, open and socket created I/O are blocked I/O)
"2" non-blocking I/O (can be set to non-blocking I/O by using the O_nonblock parameter with FCNTL or open)
"3" I/O multiplexing (I/O multiplexing, usually with non-blocking I/O)
"4" signal-driven I/O (SIGIO)
"5" Asynchronous I/O
In general, there are two steps to a program's input operation:
1. Waiting for data to be read
2. Copies data from the system kernel to the data area of the program.
For sock programming:
The first step: generally waiting for data to be uploaded locally from the network. When the 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 into the data area of the program.
Block I/O mode//process in blocking mode, give up CPU, go to sleep state
Blocking I/O mode is the most commonly used I/O pattern. is the default IO mode for Linux systems.
Most programs use blocking mode I/O.
The mode in which a socket is established is blocking I/O mode. (because the default IO mode of the Linux system is blocking mode)
For a UDP socket, the data-ready flag is relatively simple:
(1) An entire data report has been received
(2) Not received.
The concept of TCP is more complex and requires some additional variables.
A process calls Recvfrom, and then the system call does not return knowing that a datagram arrives on the local system, and then the system copies the data into the process's cache. (If the system call receives an interrupt signal, its call is interrupted)
We call this process to be blocked when calling recvfrom until the time it returns from Recvfrom. When Recvfrom returns normally, our process continues its operation.
Non-blocking mode I/O//nonblocking mode is not commonly used because non-blocking mode wastes a lot of CPU resources.
When we set a socket to non-blocking mode, we tell the system kernel: "When I request I/O operation can not be completed immediately, you want my process to hibernate wait time, do not do so, please immediately return an error to me." ”
We started three calls to Recvfrom because the system has not yet received the network data, so the kernel immediately returns a ewouldblock error.
The last time we call the Recvfrom function, a datagram has arrived, the kernel copies it into the buffer of our application, and then Recvfrom returns normally, we can process the received data.
When an application uses a non-blocking mode socket, it needs to use a loop to not listen for a test whether a file descriptor has data readable (called polling (polling)). The application keeps polling the kernel to check if I/O operations are ready. This will be a very wasteful operation of CPU resources. This pattern is not very common in use.
For example, the operation of pipelines, it is best to use non-blocking way!
I/O multiplexing//For batch IP operations, I/O multiplexing is very good.
When I am using I/O multiplexing, we call the Select () function and the poll () function or the Epoll function (the 2.6 kernel begins to support) and block when they are called, rather than when we call Recvfrom (or recv).
When we call the Select function to block, the Select function waits for the datagram socket to enter the read-ready state. When the Select function returns, that is, when the socket can read the data. We can then call the Recvfrom function to copy the data into our program buffer.
For a single I/O operation, compared to the blocking mode, select () and poll () or epoll do not have much of an advanced place. Also, in blocking mode, you only need to call a function: Read or send the function. After using multiplexing, we need to call two functions: Call the Select () function or the poll () function before you can actually read and write.
The advanced approach to multiplexing is:
It can wait for multiple file descriptors at the same time, and any one of these file descriptors (socket descriptors) goes into a read-ready state, and the Select () function returns.
IO multiplexing is generally used in the following cases:
1, when a client needs to handle the input and output operations of multiple file descriptors simultaneously (generally standard input and output and network sockets), I/O multiplexing technology will have the opportunity to be used.
2, when the program needs to do multiple sockets at the same time.
3. If a TCP server program handles both sockets that are listening for network connections and sockets that are already connected.
4. If a server program uses both the TCP and UDP protocols.
5. If a server uses multiple services at the same time and each service may use a different protocol (such as inetd). Asynchronous IO modes are:: 1, signal-driven I/O mode 2, asynchronous I/O mode
Signal-driven I/O mode//I have not used it.
We can use the signal to let the kernel use the SIGIO signal to notify us when the file descriptor is ready. We refer to this mode as the signal-driven I/O mode.
In order to use the signal-driven I/O operation on a socket, the following three steps are required.
(1) The processing function of one and Sigio signals must be set.
(2) The owner of the socket must be set up. In general, use the F_setown parameter of the FCNTL function to
The owner of the setting.
(3) Sockets must be allowed to use asynchronous I/O. This is usually done by calling the F_SETFL command of the FCNTL function, O_async as a parameter.
Although it is very simple to set the socket as asynchronous I/O, the difficult part is how the program is in the process of determining when the Sigio signal is sent to the socket owner.
1. SIGIO signal for UDP sockets (relatively simple)
Using Sigio on the UDP protocol is very simple. This signal will be generated at this time: 1, the socket received a datagram packet.
2. The socket has an asynchronous error.
When we use UDP socket asynchronous I/O, we use the Recvfrom () function to read datagram data or asynchronous I/O error messages.
2. SIGIO signal for TCP sockets (because of the complexity, the actual general use of the socket asynchronous IO)
Unfortunately, SIGIO has little effect on TCP sockets. Because the probability of a SIGIO signal occurring is too high for a TCP socket, the SIGIO signal does not tell us what is going on. In a TCP connection, the SIGIO signal will be generated at this time:
L successfully established a new connection on a socket that listens on a port.
L A request for disconnection was successfully initialized.
L The request for a broken line ends successfully.
A certain channel of the socket (send channel or receive channel) is closed.
L socket receives new data.
L sockets send the data out.
L An error occurred with an asynchronous I/O.
A practical aspect of signal-driven I/O is the NTP (Network Time Protocol networks Protocol) server, which uses UDP. The primary loop of this server is used to receive datagram packets sent from the client before sending the request. It is important for this server to record the exact time it takes to receive each packet.
Because that will be the value returned to the client, the client will use this data to calculate the time it takes for the datagram to go back and forth on the network. Figure 6-8 shows how to create such a UDP server.
asynchronous I/O mode//such as write operations, only write, not necessarily write to disk (this is asynchronous I/O) benefits. The benefits of asynchronous IO are high efficiency.
When we run in asynchronous I/O mode, if we want to do I/O, we just need to tell the kernel that we are going to do I/O and then the kernel will return immediately. The specific I/O and copies of the data are all done by the kernel, and our program can continue to execute down. When the kernel completes all I/O operations and copies of the data, the kernel notifies our program.
The difference between asynchronous I/O and signal-driven I/O is:
1. In the signal-driven I/O mode, the kernel notifies our application when the operation can be manipulated to send Sigio messages.
2. In asynchronous I/O mode, the kernel notifies our application only after all operations have been completed by the kernel operation.
Five I/O modes-blocking (default IO mode), non-blocking (common language pipeline), I/O multiplexing (IO multiplexing scenario), signal I/O, asynchronous I/O