An IO task is a process in which a program reads data from a file or writes data to a file, a process that generally requires the CPU to control it. For example, a network IO task.
Or a local file IO task.
In some cases, IO operations cannot be completed immediately. For example, in network IO, the process calls accept to try to receive a client connection, but at this time there is no client initiating the connection, so how does the process handle the execution of the accept function? At this point, the concept of blocking and non-blocking comes into play.
Blocking and interrupting programs
When the CPU executes process tasks, it divides the computing resources by time slice, and the processes that need to use the CPU are queued in the work queue, and the CPU takes turns to take out processes from the queue, allocate time slices and execute tasks. Suppose at this time process A executes the accept function, but the client does not initiate a connection, then if nothing is done, process A will remain in the work queue and keep getting stuck at the place where the accept function is executed, and the CPU usage is 100%.
So at this point the system needs to adopt some strategies to avoid meaningless computational resource consumption.
When the accept function is executed, but the client does not initiate a connection, the system removes process A from the work queue and puts it in the wait queue of accept’s socketfd. At this point, the CPU executes the task without allocating any time slice to process A. We call process A a blocking state. So when does the execution of process A resume?
Interrupting a process
After the client initiates the connection and the NIC receives the data, it executes an interrupt program to interrupt the current CPU task, which does two things: 1. copies the data received by the NIC to the kernel buffer (i.e., the socket’s receive buffer) and 2. puts process A back in the execution queue. when the CPU executes the process task again, the accept function gets the client connection data and the program continues to execute normally. The program continues to execute normally.
Now to understand blocking a little more.
- It is inefficient for a single process, once it enters the blocking state, the process cannot perform other tasks.
- Efficient for the system as a whole, allowing processes that do not need to continue to execute to enter a blocking state, giving up CPU and increasing the processing power of the system.
Some operations involving blocking
There are quite a few operations that can cause a process to block, here is a small list of those covered in this article, more will be sorted out later.
Receive connections and read data.
Start the server-side program and start multiple client programs to initiate connections and then send data.
As you can see, with blocking io, a process can only process one connection at a time, and other connections need to wait for the previous connection to be disconnected before they can be processed.