Understand the IO model in half an hour

关注+星标公众号,不错过精彩内容


转自 | 掘金技术社区

1. Background

I have been tossing about network programming recently and found that the IO model is relatively vague. I have read a lot of information and will summarize and share it here. Keywords: network programming; IO model

2. Pre-knowledge 1: kernel mode, user mode

To understand the IO model, there is a batch of prerequisite knowledge that needs to be mastered. The first is the concept of kernel mode and user mode. In order to protect itself, the operating system has designed two states: user mode and kernel mode. Applications generally work in user mode. When calling some underlying operations (such as IO operations), they need to switch to kernel mode. Switching between user mode and kernel mode consumes some resources. Zero-copy technology improves performance by reducing the switching between user mode and kernel mode.

3. Prerequisite knowledge 2: The general process of the application receiving data from the network

The general flow of the server receiving from the network is as follows:

  1. The data comes to the network card through the computer network

  2. Read the data from the network card to the socket buffer

  3. Read the socket buffer into the user buffer, which can then be used by the application

outside_default.png

The core is two read operations. The difference between the five major IO models lies in how these two read operations interact.

4. Prerequisite knowledge three: Understand synchronization/asynchronous, blocking/non-blocking

Synchronization/asynchronous: This is an application-level concept. It refers to calling a function. Should we wait for the function to finish executing before continuing to the next step, or after adjusting the function, continue to the next step and start a new thread to execute the called function? function. The focus is on collaboration between threads. Blocking/non-blocking, this is a concept at the hardware level. Blocking means that the CPU is "rested" to handle other processes, such as IO operations, while non-blocking means that the CPU will still execute and will not switch to other processes. The concern is whether the CPU will be "rested", which is manifested at the application level as whether the thread will be "suspended". As for the difference between synchronization and blocking, and the difference between asynchronous and non-blocking, in fact, these are things at different levels and cannot be compared with each other. In the process of learning the IO model, don't get into trouble.

5. Prerequisite knowledge four: Understand synchronous blocking, synchronous non-blocking, asynchronous blocking, asynchronous non-blocking

There are many IO model blogs that combine synchronous/asynchronous and blocking/non-blocking, and divide IO models into four categories.

outside_default.png

At first glance, it’s actually very confusing. It’s all asynchronous, so why is it blocking?

In fact, there is no need to worry about this. Synchronization/asynchronous, blocking/non-blocking are things at different levels. Forcibly combining them is difficult to understand, or even wrong.

The suggestion is to put this aside and go directly to understand the five major IO models, and don't get into trouble. In fact, if we really want to divide it, we can only divide it into two dimensions instead of four. The first is divided by blocking/non-blocking:

outside_default.png

Then it is divided by synchronous/asynchronous:

outside_default.png

6. One of the five IO models: blocking IO

Okay, if you master the pre-knowledge mentioned above, it will be a little easier to understand the IO model, let's start now.

As mentioned before, the general process for an application to receive data from the network is two steps:

  1. Data preparation: wait for network data and read the network card data into the socket buffer

  2. Data copy: Read the data from the socket buffer to the user mode Buffer for use by the application program

The difference between the IO model lies in how these two operations interact. Let's first look at the blocking IO model.

When the application initiates a read call, the calling thread blocks until the first read operation is completed. After the first step of reading operation is completed, the data will be read into the user state Buffer. During this process, the calling thread is still blocked until the data copy is completed. The entire process is represented by a diagram like this:

outside_default.png

The advantage of this IO model is that it is easy to understand, the API is simple and easy to use, and it is suitable for network applications with a small number of connections.

7. One of the five IO models: non-blocking IO

When an application issues a read call, if there is no data to read, the calling thread will not block. But in order to read the data, the application will keep calling in a loop until there is data to read.

After the first step of reading operation is completed, the second step is the same as blocking IO. The data will be read into the user mode Buffer. During this process, the calling thread is still blocked until the data copy is completed. The entire process is represented by a diagram like this:

outside_default.png

This IO model has no special benefits, and it will keep calling the underlying interface in a loop. The performance is worrying and it is rarely used.

8. One of the five major IO models: signal-driven IO

When the application initiates a read call, it registers a handler and waits for a callback after data is available. Once the application is called back, it means that the data can be read, and the second step will be performed to read the data into the user mode Buffer. Again, the second step is still blocking.

outside_default.png

The advantage of this IO model is that compared to non-blocking IO, the use of notification & callback mechanism reduces loop overhead. However, in scenarios with a large number of connections, notification may not be possible due to signal queue overflow, so it is not used much.

9. One of the five IO models: multiplexing IO

When the application initiates a read call, if there is no data to read, the calling thread will not block. The system will register the socket to a "multiplexer". When there is data, the readable socket will be added to the queue and supplied. Use with layers.

outside_default.png

The approximate code is as follows:

java复制代码while (true) {
    if (selector.select(READ_KEY) > 0) { // selector 就是多路复用器,READ_KEY 大于 1 说明有可读的socket
        Set<SelectionKey> set = clientSelector.selectedKeys();
        Iterator<SelectionKey> keyIterator = set.iterator();
        while (keyIterator.hasNext()) { 
            SelectionKey key = keyIterator.next();
            if (key.isReadable()) {
                // 读取数据
            }
        }
    }
}

The advantage of this IO model is that it can handle a large number of connections, especially suitable for a large number of short connections. Most network applications now use multiplexed IO at the bottom layer.

10. One of the five IO models: asynchronous IO

Asynchronous IO is different from the above four IO models. It is completely asynchronous, and the two-step operation will not block. After the application initiates a read call, it can use the data in the user-mode Buffer after receiving the callback notification, as shown in the figure below.

outside_default.png

11. Use an analogy

Let me give you an analogy that I think is very appropriate to help you understand.

edd6ad18247dedb1557cdf98a3a0e5e5.jpeg

Everyone has gone to the hospital to get medicine. The five IO models are like different ways of getting medicine.

  • Blocked IO: I am waiting in line for medicine, but the medicine is not ready yet, so I will continue to wait, and no one else can take it. This kind of method that I am not good at and others cannot do well is a manifestation of blocking IO.

  • Non-blocking IO: I'm waiting in line for medicine, but the medicine is not ready yet, so I'll queue it up again. Re-queuing is polling, because re-queuing does not prevent others from canceling, which is the embodiment of non-blocking IO.

  • Signal-driven IO: No need to wait in line for medicine. When the medicine is ready, you will be notified directly by text message to pick it up. SMS notification is equivalent to signal driving, because there is no need to queue, which saves a lot of time.

  • Multiplexed IO: This is the common way to get medicine in daily life. After paying, you have to scan the code on the pharmacy machine, then stare at the monitor, which shows your name, and then get the medicine. Scanning the QR code on the machine is equivalent to registration, and displaying your name is equivalent to having an IO event that needs to be processed. In reality, my name is displayed, and I still have to queue up. This is also corresponding, because a selector returns multiple IO times that need to be processed, and processing each one is equivalent to queuing up to get medicine one by one.

  • Asynchronous IO: This is very cyberpunk. Asynchronous IO is like no need to queue or pick up medicine. Once the medicine is ready, it will be sent directly to your home. It is completely asynchronous.

12. Questions that may arise:

12.1 Java's nio is an implementation of the multiplexed IO model. Why is it called non-blocking?

First of all, Java's nio package can be used to implement multiplexed IO models, and it can also be used to implement non-blocking IO models, but the non-blocking IO model has poor performance and no one uses it. Secondly, the "n" in nio means new. At that time, in order to distinguish it from the old IO package, the JDK developers used nio to express it. It was not the "n" of nonblocking, so it was more accurate to call it "new IO package" and not easy to confuse.

12.2 What is the relationship between select, poll, and epoll?

Select, poll, and epoll are all used to implement multiplexing. The principle is to find readable and writable sockets through traversal. The difference is that

  • select has a limit, up to 1024, poll and epoll do not have this limit.

  • poll has optimized the data structure and does not have a limit of 1024, but it still needs to traverse all sockets, which is rarely used at present.

  • epoll is optimized for traversal. It will not traverse all sockets, but only those readable sockets, so the efficiency is improved.

12.3 It is difficult to distinguish between signal driven IO and multiplexed IO

The underlying mechanism of signal-driven IO is event notification, and the underlying mechanism of multiplexed IO is traversal + callback, but it is packaged into events at the application level.

13. Summary

There are two steps to reading data from the network card: the first step is from the network card to the socket buffer, and the second step is from the socket buffer to the kernel state.

There are five IO models: blocking IO, non-blocking IO, signal-driven IO, multiplexed IO, and asynchronous IO.

  • Blocking IO: blocking in both steps

  • Non-blocking IO: The first step does not block, but the application layer does not know when the data is readable, so it needs to continuously poll

  • Signal-driven IO: The first step is not blocked, but the application layer does not perceive the blocking in this step. The mechanism is an event notification mechanism. When the data is ready, the application layer is directly notified to read it.

  • Multi-channel without IO: The first step is not blocked, but the application layer does not perceive the blocking in this step. The mechanism is to traverse all Sockets and notify the application layer to read when ready.

  • Asynchronous IO: Pure asynchronous, after the data is prepared, the application layer uses it directly.

Statement: The material of this article comes from the Internet, and the copyright belongs to the original author. If there is any copyright issue with the work, please contact me to delete it.

------------ END ------------

db36b777620e2f456de278bd3ef160ef.gif

●Column "Embedded Tools "

●Column "Embedded Development"

●Column "Keil Tutorial"

●Embedded column selected tutorials

Follow the official account and reply " Add Group " to join the technical exchange group according to the rules, and reply " 1024 " to view more content.

2ecd5a9f89e90f2d58c95b3aae7e9ca5.jpeg

ec29fcbc8a69dda0b863d0b87cada4f3.png

Click " Read the original text " to view more sharing.

Guess you like

Origin blog.csdn.net/ybhuangfugui/article/details/132594442