that , At the beginning of the ceremony Linux IO Before the model , such as ： Sync IO And asynchronous IO, Blocking IO And non blocking IO What are the differences , What's the difference ？ Different people give different answers in different contexts . So first limit the context of this article .
1 Concept description #
Before explaining , First of all, several concepts should be explained ： User space and kernel space Process switching Process blocking File descriptor cache IO 1.1 User space and kernel space ##
Now the operating system uses virtual memory , So right. 32 Bit operating system , Its addressing space （ Virtual storage space ） by 4G（2 Of 32 Power ）. The core of the operating system is the kernel , Independent of ordinary applications , Access to protected memory space , You also have all access to the underlying hardware devices . To ensure that the user process cannot directly operate the kernel （kernel）, Keep the kernel safe , The operating system divides the virtual space into two parts , Part of it is kernel space , Part of it is user space . in the light of linux In terms of operating system , Will be the highest 1G byte （ From virtual address 0xC0000000 To 0xFFFFFFFF）, For kernel use , It's called kernel space , And the lower 3G byte （ From virtual address 0x00000000 To 0xBFFFFFFF）, For each process , It's called user space .
1.2 Process switching ##
In order to control the execution of the process , The kernel must have the ability to suspend being CPU Process running on , And resume the execution of a previously suspended process . This behavior is called process switching . So we can say , Any process runs with the support of the operating system kernel , Is closely related to the kernel . Moving from one process to another , This process goes through the following changes ：
- Save processor context , Including program counter and other registers .
- to update PCB Information .
- Put the process of PCB Move into the appropriate queue , If you are ready 、 In an event blocking queue .
- Choose another process to execute , And update it PCB.
- Update the data structure of memory management .
- Recover processor context .
notes ： All in all, it's very resource intensive , For details, please refer to this article ： Process switching .
You need the above information or Linux Information please +qun832218493 Free collection ！
1.3 Process blocking ##
Process in progress , Because some of the expected events did not happen , If the request for system resources fails 、 Wait for an operation to complete 、 New data has not arrived or no new work has been done , The system will automatically execute the blocking primitive (Block), Change from running state to blocking state . so , Process blocking is an active behavior of the process itself , So there are only running processes （ get CPU）, It's possible to turn it into a blocked state . When the process is blocked , It doesn 't take CPU Resources .
1.4 File descriptor fd##
File descriptor （File descriptor） It's a term in computer science , Is an abstract concept used to express references to files . The file descriptor is a non negative integer in form . actually , It's an index value , The log table that points to the file opened by the kernel for each process . When the program opens an existing file or creates a new file , The kernel returns a file descriptor to the process . In programming , Some of the underlying programming often revolves around file descriptors . But the concept of file descriptors often only applies to UNIX、Linux Such an operating system .
1.5 cache IO##
cache IO Also known as the standard IO, Default for most file systems IO Operations are all caching IO. stay Linux The cache of IO In mechanism , The operating system will IO The data is cached in the file system's page cache （ page cache ） in , in other words , The data will be copied to the buffer of the operating system kernel first , Then it will copy from the buffer of the operating system kernel to the address space of the application .
cache IO The shortcomings of ： Data in the process of transmission needs to be copied in the application address space and the kernel many times , What these data copying operations bring CPU And memory overhead is very large .
2 Linux IO Model #
The Internet IO The essence is socket The read ,socket stay linux The system is abstracted as a stream ,IO It can be understood as the operation of convection . Said just now , For once IO visit （ With read give an example ）, The data will be copied to the buffer of the operating system kernel first , Then it will copy from the buffer of the operating system kernel to the address space of the application . So , When one read When the operation occurs , It goes through two stages ：
- The first stage ： Wait for the data to be ready (Waiting for the data to be ready).
- The second stage ： Copy data from the kernel into the process (Copying the data from the kernel to the process).
about socket In terms of flow ,
- First step ： It usually involves waiting for data packets on the network to arrive , Then it's copied to a buffer in the kernel .
- The second step ： Copy data from kernel buffer to application buffer .
Network applications need to deal with two kinds of problems , The Internet IO, Data calculation . Compared with the latter , The Internet IO Delay of , The performance bottleneck brought to the application is greater than the latter . The Internet IO There are several models of ：
- Synchronous model （synchronous IO）
- Blocking IO（bloking IO）
- Non blocking IO（non-blocking IO）
- Multiplexing IO（multiplexing IO）
- Signal driven IO（signal-driven IO）
- asynchronous IO（asynchronous IO）
notes ： because signal driven IO Not commonly used in practice , So I'll just mention the four remaining IO Model. In depth introduction to Linux IO Before the various models , Let's explore the basics first Linux IO The simple matrix of the model . As shown in the figure below ：
Input picture description Every IO Models have their own usage patterns , They all have their own advantages for specific applications . This section will briefly introduce each of them . common IO There's a blockage in the model 、 Non blocking 、IO Multiplexing , asynchronous . A vivid example is given to illustrate these four concepts . I go shopping with my girlfriend on the weekend , I'm hungry at noon , We're going to eat . There are many people on weekends , You need to line up for dinner , My girlfriend and I have the following plans .
2.1 Synchronous blocking IO（blocking IO）##
2.1.1 Scene description ### My girlfriend and I ordered after dinner , I don't know when I can do it well , I have to sit in the dining room and wait , Until it's done , And then eat and leave . My girlfriend wanted to go shopping with me , But I don't know when the meal will be ready , I had to wait in the restaurant with me , You can't go shopping , You can't go shopping until you've finished your meal , The time in the middle of waiting to cook was wasted . This is a typical blockage . 2.1.2 A network model ### Synchronous blocking IO A model is the most commonly used model , It's also the simplest model . stay linux in , By default, all socket All are blocking. It's in line with the most common logic of thinking . Blocking is a process " By " rest , CPU To deal with other processes . In this IO In the model , User space applications perform a system call （recvform）, This can cause the application to block , Do nothing , Until the data is ready , And copy the data from the kernel to the user process , Finally, the process processes the data , Two stages from waiting for data to processing data , The whole process is blocked . Can't handle other networks IO. Calling the application is in a way that no longer consumes CPU It's just the state of simply waiting for a response , So from a processing point of view , It's very effective . Calling recv()/recvfrom() Function time , The process of waiting for and copying data in the kernel , It's roughly as follows ：
Input picture description 2.1.3 Process description ### When the user process calls recv()/recvfrom() This system call ,kernel He began IO The first stage of ： Prepare the data （ For network IO Come on , Many times the data hasn't arrived at the beginning . such as , I haven't received a complete UDP package . This is the time kernel Just wait for enough data to come ）. This process needs to wait , That is to say, it needs a process to copy the data to the buffer of the operating system kernel . On the user process side , The whole process will be blocked （ Of course , It's the process's own choice of blocking ）. Second stage ： When kernel Wait until the data is ready , It will take data from kernel Copy to user memory , then kernel Return results , The user process is released block The state of , Run it again . therefore ,blocking IO It is characterized by IO Both phases of implementation are block 了 . advantage ：
- Able to return data in time , No delay ;
- It's easy for kernel developers ;
- For users, waiting is the price of performance ;
2.2 Synchronous nonblocking IO（nonblocking IO）##
2.2.1 Scene description ### My girlfriend is not willing to wait here for nothing , I want to go shopping again , I'm worried about the meal again . So let's hang out for a while , Come back and ask the waiter if the meal is ready , Back and forth many times , I'm so tired that I haven't eaten yet . This is non blocking . It needs constant questioning , Are you ready to . 2.2.2 A network model ### Synchronous non blocking is “ Take a look at the progress bar every once in a while ” The polling （polling） The way . In this model , The device is opened in a non blocking way . It means IO The operation will not be completed immediately ,read The operation may return an error code , It means that this order cannot be satisfied immediately （EAGAIN or EWOULDBLOCK）. On the Internet IO When , Non blocking IO There will be recvform system call , Check that the data is ready , And blocking IO Dissimilarity ," Nonblocking divides a large block of time into N Many little jams , So the process continues to have opportunities ' By ' CPU Patronize ". That is to say, non blocking recvform After the system call , The process is not blocked , The kernel immediately returns to the process , If the data is not ready , This will return to a error. After the process returns , You can do something else , And then launch recvform system call . Repeat the process above , Go back and forth recvform system call . This process is often called polling . Polling for kernel data , Until the data is ready , Then copy the data to the process , Data processing . We need to pay attention to , The whole process of copying data , The process is still in a blocked state . stay linux Next , Can be set by socket Turn it into non-blocking. When it comes to one non-blocking socket When reading , The flow is as shown in the figure ：
Input picture description 2.2.3 Process description ### When the user process issues read In operation , If kernel The data in is not ready , Then it won't block User process , But immediately return to a error. From the perspective of user process , It launched a read After the operation , There is no need to wait , It's about getting an immediate result . The result of user process judgment is a error when , It knows the data is not ready , So it can send... Again read operation . once kernel The data in is ready , And again received the user process's system call, Then it immediately copies the data to the user memory , Then return . therefore ,nonblocking IO It is characterized by continuous active inquiry of user process kernel Is the data ready . Synchronous non blocking mode is compared with synchronous blocking mode ： advantage ： Be able to do other work while waiting for the task to be completed （ Including submitting other tasks , That is to say “ backstage ” You can have multiple tasks executing at the same time ）. shortcoming ： The response delay for task completion increases , Because it takes a while to poll read operation , The task may be completed at any time between polls . This leads to a reduction in overall data throughput . 2.3 IO Multiplexing （ IO multiplexing）##
2.3.1 Scene description ### Similar to the second one , The restaurant has installed an electronic screen to show the status of the order , I'll go shopping with my girlfriend for a while , You don't have to ask the waiter when you come back , Just look at the electronic screen . Is this a good meal for everyone , Just look at the electronic screen , That's typical IO Multiplexing . 2.3.2 A network model ### Because the synchronous non blocking mode requires continuous active polling , Polling is a big part of the process , Polling consumes a lot of CPU Time , and “ backstage ” There may be multiple tasks at the same time , People think of looping through the completion status of multiple tasks , As long as any task is completed , Just deal with it . If polling is not the user state of the process , It's just someone to help . So this is the so-called “IO Multiplexing ”.UNIX/Linux Under the select、poll、epoll That's what it's for （epoll Than poll、select Efficient , It's the same thing ）.
IO Multiplexing has two special system calls select、poll、epoll function .select The call is kernel level ,select The difference between polling and non blocking polling is --- The former can wait for more than one socket, It can realize simultaneous and multiple IO Port for listening , When any of them socket The data is accurate , Can be returned for readability , Then the process goes on recvform system call , Copy data from kernel to user process , Of course, the process is blocked .select or poll After call , It's blocking the process , And blocking IO The difference between blocking and blocking is , At this time select Not until socket Data all arrive and then process , But with some data, the user process will be called to process . How to know that some data has arrived ？ The monitoring was left to the kernel , The kernel is responsible for data arrival processing . It can also be understood as " Non blocking " Well .
I/O The reuse model uses select、poll、epoll function , These functions also block the process , But with blocking I/O What's different , These two functions can block multiple I/O operation . And it can read multiple operations at the same time , Multiple write operations I/O Function to detect , Until data is readable or writable （ Note that not all data is readable or writable ）, To really call I/O Operation function .
For multiplexing , That is, polling multiple socket. Since multiplexing can handle multiple IO, It also brings new problems , Multiple IO The order between them becomes uncertain , Of course, it can also be used for different numbers . Specific process , As shown in the figure below ：
Input picture description 2.3.3 Process description ### IO multiplexing That's what we said select,poll,epoll, Some places also call this IO The way is event driven IO.select/epoll The good thing about it is that it's a single process You can handle multiple network connections at the same time IO. Its basic principle is select,poll,epoll This function Will constantly poll all the socket, When a socket There's data coming in , Just inform the user of the process .
When the user process calls select, Then the whole process will be block, At the same time ,kernel Meeting “ monitor ” all select conscientious socket, When any one socket The data in is ready ,select It will return . At this time, the user process calls read operation , Take data from kernel Copy to user process . Multiplexing is characterized by a mechanism in which a process can wait at the same time IO File descriptor , The kernel monitors these file descriptors （ socket descriptor ）, Any one of them enters the read ready state ,select, poll,epoll The function returns . For the way you watch , Can be divided into select, poll, epoll Three ways . The picture above and blocking IO It's not that different , in fact , It's worse . Because we need to use two system call (select and recvfrom), and blocking IO Only one was called system call (recvfrom). however , use select The advantage is that it can handle multiple connection. therefore , If the number of connections processed is not very high , Use select/epoll Of web server It's not necessarily better than using multi-threading + blocking IO Of web server Better performance , Maybe the delay is even greater .（select/epoll The advantage is not that you can handle a single connection faster , It's about being able to handle more connections .） stay IO multiplexing Model in , In the actual , For each of these socket, It's usually set to non-blocking, however , As shown in the figure above , For the entire user process In fact, it has been block Of . It's just process Be being select This function block, Rather than being socket IO to block. therefore IO Multiplexing is blocking in select,epoll On top of such system calls , And there's no blocking in the real I/O System calls such as recvfrom above . stay I/O During programming , When multiple client access requests need to be processed at the same time , You can use multithreading or I/O Multiplexing technology for processing .I/O Multiplexing technology by putting multiple I/O The blocks are multiplexed to the same select On the block , Thus, the system can process multiple client requests at the same time in the case of single thread . With traditional multithreading / Multi process model ,I/O The biggest advantage of multiplexing is low system overhead , The system does not need to create new extra processes or threads , There is no need to maintain the running of these processes and threads , Reduce the maintenance workload of the system , Save system resources ,I/O The main application scenarios of multiplexing are as follows ： The server needs to process multiple sockets that are listening or connected at the same time . The server needs to handle multiple network protocol sockets at the same time . I know the first three IO Pattern , When a user process makes a system call , They're waiting for the data to arrive , The way to deal with it is different , Just wait , polling ,select or poll polling , Two stage process ： There was a blockage in the first stage , Some don't block , Some can be blocked or not blocked . The second stage is blocked . From the whole IO In the process , They are all sequential , So it can be classified as a synchronous model (synchronous). It is the process that waits actively and checks the status to the kernel .【 This sentence is very important ！！！】
High concurrency programs generally use synchronous non blocking rather than multithreading + Synchronous blocking mode . To understand that , First of all, the difference between concurrency and parallelism . For example, to go to a certain department, you need to go to several windows in turn , The number of people in the service hall is the concurrent number , And the number of windows is parallelism . In other words, concurrent number refers to the number of simultaneous tasks （ Such as serving at the same time HTTP request ）, And parallel number is the number of physical resources that can work at the same time （ Such as CPU Check the number ）. By reasonably scheduling different stages of the task , Concurrency can be much greater than parallelism , This is just a few CPU The secret of supporting tens of thousands of concurrent requests . In this case of high concurrency , For each task （ User request ） Creating a process or thread is very expensive . And the synchronous non blocking mode can put multiple IO Ask to leave it backstage , This can serve a lot of concurrency in a process IO request . Be careful ：IO Is multiplexing a synchronous blocking model or an asynchronous blocking model , Let's give you an analysis ： It's still not clear here , It is strongly recommended that you study 《 Talk about synchronization 、 asynchronous 、 Blocking and non blocking 》 The fundamental difference between synchronous and asynchronous , Synchronization requires active waiting for message notification , Asynchronism is passively receiving message notification , Through the callback 、 notice 、 State and other ways to passively obtain messages .IO Multiplexing is blocking to select When the stage , The user process is actively waiting and invoking select Function to get the data ready status message , And its process state is blocked . therefore , hold IO Multiplexing is classified as synchronous blocking mode .
2.4 Signal driven IO（signal-driven IO）##
Signal driven I/O： First of all, we allow Socket Signal drive IO, And install a signal processing function , The process continues to run without blocking . When the data is ready , The process will receive a SIGIO The signal , It can be called in the signal processing function I/O Operating functions process data . The process is shown in the figure below ：
Input picture description 2.5 Asynchronous non-blocking IO（asynchronous IO）##
2.5.1 Scene description ### My girlfriend doesn't want to go shopping , The restaurant is too noisy , Go home and have a good rest . So we ordered takeout , Make a phone call and order , Then my girlfriend and I can have a good rest at home , The meal is ready and the deliveryman brings it home . This is typical asynchronous , Just call and say , And then you can do your own thing , When the meal is ready . 2.5.2 A network model ### Relative to synchronization IO, asynchronous IO Not in sequence . The user process goes on aio_read After the system call , Whether the kernel data is ready or not , Will be returned directly to the user process , Then the user mode process can do something else . wait until socket The data is ready , The kernel copies data directly to the process , It then sends a notification to the process from the kernel .IO Two phases , Processes are non blocking . Linux Provides AIO Library functions implement asynchrony , But it's rarely used . There's a lot of open source asynchrony right now IO library , for example libevent、libev、libuv. The asynchronous process is shown in the following figure ：
Input picture description
2.5.3 Process description ###
User process initiation aio_read After the operation , You can start doing other things right away . And on the other hand , from kernel The angle of , When it receives a asynchronous read after , First of all, it will return to , So it doesn't produce anything to the user process block. then ,kernel Waiting for the data to be ready , Then copy the data to user memory , When all this is done ,kernel A... Will be sent to the user process signal Or execute a thread based callback function to do this IO Treatment process , Tell it read Operation completed .
stay Linux in , The way of notification is “ The signal ”：
If the process is busy doing something else in user mode （ For example, in calculating the product of two matrices ）, Then force the interruption , Call a pre registered signal processing function , This function can determine when and how to handle this asynchronous task . Because the signal processing function is suddenly burst in , So it's like an interrupt handler , There are a lot of things that can't be done , So to be on the safe side , It's usually the event “ registration ” As soon as you drop into the queue , And then go back to what the process was doing .
If the process is busy doing something else in kernel mode , For example, read and write disks in synchronous blocking mode , Then we have to hang up the notice , When the kernel state is busy , It's about to return to user mode , And then trigger the signal to inform . If the process is now suspended , There is nothing to do sleep 了 , Then wake up the process , Next time there will be CPU In my spare time , It will be scheduled to this process , Trigger signal notification . asynchronous API It's light to say , It's hard to do , This is mainly about API For the implementers of .Linux The asynchronous IO（AIO） Support is 2.6.22 It was introduced , Many asynchronous system calls are not supported IO.Linux The asynchronous IO It was originally designed for databases , So through asynchronous IO The read and write operations of are not cached or buffered , This can't take advantage of the operating system's caching and caching mechanism .
Many people put Linux Of O_NONBLOCK Think it's asynchronous , But in fact, this is the synchronous non blocking method mentioned above . It's important to point out that , although Linux Upper IO API A little rough , But every programming framework has encapsulated asynchrony IO Realization . The operating system does less , Leave more freedom to users , It is UNIX Philosophy of design , It's also Linux One of the reasons why programming frameworks are blooming .
From the front IO In the classification of models , We can see that AIO The motive of ： The synchronous blocking model needs to be in IO Blocking the application at the beginning of the operation . This means that it is not possible to overlap processing and IO operation . The synchronous non blocking model allows processing and IO Operations overlap , But this requires the application to check against the rules of recurrence IO State of operation . That leaves asynchronous non blocking IO 了 , It allows processing and IO Operations overlap , Include IO Notice of completion of operation . IO In addition to the need for multiplexing blocking ,select The function provides （ Asynchronous blocking IO） And AIO similar . however , It's blocking notification events , Not right. IO Call to block .
2.6 About asynchronous blocking ##
Sometimes our API Only asynchronous notification is provided , For example, in node.js in , But what business logic needs is to do one thing after another , For example, only after the database connection is initialized can the user's HTTP request . Such business logic requires the caller to work in a blocking manner .
To simulate in an asynchronous environment “ Sequential execution ” The effect of , You need to convert synchronous code to asynchronous form , This is called CPS（Continuation Passing Style） Transformation .BYVoid The great god continuation.js A library is a CPS Tools of transformation . Users only need to write code in a synchronous way that conforms to human common sense ,CPS The converter will convert it into a nested layer of asynchronous callbacks .
Input picture description
Input picture description Another reason to use blocking is to reduce response latency . If non blocking mode is adopted , A task A Submitted to the background , Just start doing another thing B, but B It's not finished yet ,A It's done. , At this time, we want to let A The completion of the event was handled as soon as possible （ such as A It's an emergency ）, Or throw away half done B, Or save it B And switch back to A, Task switching takes time （ Whether it's loading from disk to memory , Or load from memory to cache ）, This is bound to reduce A Response speed of . therefore , Transactions that are sensitive to real-time systems or latency , Sometimes blocking is better than non blocking .
3 Five kinds IO Model summary #
3.1 blocking and non-blocking difference ## call blocking IO Will always be block Live in the corresponding process until the operation is completed , and non-blocking IO stay kernel If the data is ready, it will return immediately . 3.2 synchronous IO and asynchronous IO difference ## In explanation synchronous IO and asynchronous IO Before the difference , We need to define them first .POSIX That's how it's defined ： A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes; An asynchronous I/O operation does not cause the requesting process to be blocked; The difference between the two is synchronous IO do ”IO operation” Will be process Blocking . By this definition , As mentioned before blocking IO,non-blocking IO,IO multiplexing All belong to synchronous IO. Someone will say ,non-blocking IO Not by block ah . Here's a very “ The cunning ” The place of , The definition of ”IO operation” It means the real IO operation , It's in the example recvfrom This system call.non-blocking IO In execution recvfrom This system call When , If kernel The data is not ready , Not at this time block process . however , When kernel When the Chinese data is ready ,recvfrom Will transfer data from kernel Copy to user memory , At this time the process is being block 了 , In the meantime , The process is being block Of . and asynchronous IO Is not the same , When the process starts IO After the operation , Just go straight back and ignore , until kernel Send a signal , Tell the process to say IO complete . In the whole process , The process has not been block. each IO Model The comparison is shown in the figure ：
Input picture description Through the picture above , You can find non-blocking IO and asynchronous IO The difference is still obvious . stay non-blocking IO in , Although the process will not be block, But it still requires the process to be proactive check, And when the data is ready , It also needs the process to call again recvfrom To copy data to user memory . and asynchronous IO It's totally different . It's like the user process will take the whole IO The operation was handed over to others （kernel） complete , And then they signal when they're done . in the meantime , User processes don't need to check IO State of operation , There's no need to actively copy data .