I recently learned the I/O model and suddenly thought of the I/O model of epoll. To study this problem, we must first know which I/O models are commonly used.
Common Io models are as follows:
Blocking IO: The program is blocked until Io is available. The simplest I/O model. The recvfrom receiving function you call usually belongs to this model.
Non-blocking IO: The program returns immediately after calling the IO function, regardless of whether the current IO is available or not. If you set the socket to non-blocking mode, you are using this model.
Reuse IO: The program blocks multiple Io file descriptors and returns when at least one Io is available. Select is Io multiplexing.
Signal-driven IO: When I/O is available, the program is interrupted and corresponding processing functions are executed to read and write Io. Other time programs can normally execute other commands.
Asynchronous IO: The difference between asynchronous Io and signal-driven Io is that asynchronous Io will notify the program to process the IO data (from the kernel to the user layer.
After reading these models, we also need to know the basic epoll mechanism. In epoll, You need to register the relevant Io events with epoll in advance, and then call epoll's main cycle epoll_wait (). Then, when an IO event occurs, the function returns the set of Io events that occur, and handed over to the user for processing.
Obviously, epoll is not the first two models. The problem is which of the following is epoll.
First, reuse Io. The main feature of Io reuse is to block Multiple I/O operations and return when an I/O is available. Epoll_wait needs to be called in epoll, and then epoll_wait returns the available Io processing and submits it to the user for processing. In this case, we usually need to call functions such as Recv to read and write Io. In this analysis, epoll conforms to all the features of the reusable Io model, and epoll uses the same method as selec.
Then look at the signal-driven Io. The signal-driven Io feature is that when I/O is available, the program is interrupted and then the interrupt function is used to process Io events. In epoll, We need to execute the main cyclic function to wait for the IO event, and the IO event is handled by the next program, rather than automatically handled by a callback function, therefore, epoll obviously does not belong to the signal drive.
Finally, let's look at asynchronous Io. Asynchronous Io is characterized by the system notifying the program to process the IO data after it is prepared. Epoll only tells you which Io is available and some registration information about this Io. To get the IO data, you need to call the Recv and other functions to copy the kernel. Therefore, epoll is not asynchronous Io.
In summary, epoll, like select, belongs to the IO Reuse Model. It should also be said that although epoll itself is an IO multiplexing model, some of its internal implementations actually use the features of signal-driven I/O and asynchronous I/O, this is because epoll depends on interruptions to determine whether Io is available. However, once encapsulated into the user, it becomes a reusable Io model. If you want to implement signal-driven Io or reuse Io, you only need to encapsulate epoll. For example, you can open another thread to call the epoll main loop and process received packets, which is equivalent to signal-driven Io. If a message queue is added, the data packet is first stored in the message queue when it comes, and then other threads process the accumulated data packets in the message queue, which is equivalent to asynchronous Io.