Foreword : I reviewed multiplexing when I learned socket programming before sorting out. I searched for relevant information and learned that multiplexing also has limitations. In the spirit of breaking the casserole question to the end, I finally found the knowledge points about the IO model.
I. Overview
Five IO models are mentioned in the book "Unix Network Programming", namely: blocking IO, non-blocking IO, multiplexed IO, signal driven IO, and asynchronous IO.
We will introduce and implement these 5 models here. Before introducing, please allow me to quote a certain metaphor
Block IO , send a text message to the goddess, saying that I am looking for you, and then silently wait for the goddess to come downstairs.During this period, you will not do anything other than waiting for you, which is a spare tire practice.
Non-blocking IO , send a text message to the goddess, if you don't reply, then send it again, and send it until the goddess comes downstairs. During this period, you will not do anything other than text messages and wait, which is a dedicated practice.
IO multiplexing is to find an aunt to help you monitor the girls who are going downstairs. During this period, you can do other things. For example, you can watch other girls by the way, play King Glory, go to the toilet, etc. IO Reuse also includes select, poll, and epoll modes. So what is the difference between them?
- 1) Aunt Select Every girl goes downstairs, Aunt Select does not know if this is your goddess, she needs to ask one by one,
and the ability of Aunt Select is still limited, and can monitor 1024 girls at most once - 2) Aunt Pol does not limit the number of girls staring at, as long as it is a girl passing by the door of the dormitory, she will help you ask if it is your goddess
- 3) Aunt epoll does not limit the number of girls staring at, and there is no need to ask one by one. So how to do it? Aunt epoll will put a big note on the face of every girl who enters the dormitory, and write the girl herself on it As long as the girl goes downstairs, aunt epoll will know if this is your goddess, and then the aunt will notify you. The above sync IO has one thing in common is that when the goddess walks out of the door of the dormitory, you are already standing at the door of the dormitory Waiting for the goddess, now you are in a blocked state
Next is the case of asynchronous IO:
you tell the goddess that I am coming, and then you go to play the game, until the goddess is downstairs, and found that she can't see you, the goddess will call you to inform you and say that I am downstairs , Where are you? Only then did you come to the door of the dormitory. This is a counterattack approach
Two, blocking IO and non-blocking IO
In Linux system programming, we introduced the concept of blocking in the chapter about concepts. Then it is easy to understand what is blocking IO and non-blocking IO. Look directly at the picture
1. Blocking IO
The most traditional IO model is that blocking occurs in the process of reading and writing data.
After the user thread issues an IO request, the kernel will check whether the data is ready, if it is not ready, it will wait for the data to be ready, and the user thread will be in a blocked state, and the user thread will hand over the CPU. When the data is ready, the kernel copies the data to the user thread, and returns the result to the user thread, and the user thread releases the block state.
code show as below:
printf("Calling recv(). \n");
ret = recv(socket, recv_buf, sizeof(recv_buf), 0);
printf("Had called recv(). \n");
Some people may say that multithreading + blocking IO can be used to solve the efficiency problem, but because in multithreading + blocking IO, each socket corresponds to a thread, which will cause a lot of resource occupation, and especially for long connections. In other words, thread resources will never be released. If there are many connections in the future, it will cause a performance bottleneck.
2. Non-blocking IO
When the user thread initiates an IO operation, it does not need to wait, but gets a result immediately. If the result is an error, it knows that the data is not ready, so it can send IO operations again. Once the data in the kernel is ready, and it receives a request from the user thread again, it immediately copies the data to the user thread and then returns.
In the non-blocking IO model, user threads need to constantly ask whether the kernel data is ready, that is, non-blocking IO will not hand over the CPU, but will always occupy the CPU.
For non-blocking IO, there is a very serious problem. In the while loop, you need to constantly ask whether the kernel data is ready, which will lead to a very high CPU usage, so in general, the while loop is rarely used to read data.
code show as below:
while(1)
{
printf("Calling recv(). \n");
ret = recv(socket, recv_buf, sizeof(recv_buf), 0);
if (EAGAIN == ret) {
continue;}
else if(ret > -1) {
break;}
printf("Had called recv(), retry.\n");
}
The editor recommends my own linuxC/C++ language technology exchange group: [ 1106675687 ] I have compiled some learning books and video materials that I think are better to share in the group files, and you can add them if you need them!