Overview of 5 IO Models of Unix

    There are five I/O models available under Unix: blocking I/O, non-blocking I/O, I/O multiplexing (select and poll), signal-driven I/O (SIGIO), and asynchronous I/O (POSIX aio_ family of functions). The details of each of these models will be added later, and this section only provides a general description of them.
    An input operation usually consists of two distinct phases:
    (1) waiting for data to be ready;
    (2) copying data from the kernel to the process. For input operations on a socket, the first step usually involves waiting for data to arrive from the network. When the waiting packet arrives, it is copied to some buffer in the kernel. The second step is to copy the data from the kernel buffer to the application process buffer.
    The blocking I/O model is the most popular I/O model. All sockets are blocking by default. For simplicity, taking the datagram socket as an example (the same below), the input operation situation on the blocking I/O model is shown in the following figure.

    The process calls recvfrom, whose system call does not return until the datagram arrives and is copied into the application process's buffer or an error occurs. The most common mistake is when a system call is interrupted by a signal. We say that the process is blocked from the time recvfrom is called until it returns. After recvfrom returns successfully, the application process starts to process the datagram.
    In the non-blocking I/O model, when a process sets a socket to be non-blocking, it informs the kernel that when the requested I/O operation cannot be completed without putting the process to sleep, do not put the process to sleep, but is to return an error. The input operation situation on it is shown in the figure below.

    The first three calls to recvfrom in the figure have no data to return, so the kernel instead returns an EWOULDBLOCK error immediately. Application processes like this constantly polling the kernel to see if an operation is ready often consumes a lot of CPU time, but this model is occasionally encountered, usually in systems that specialize in a certain function.
    With I/O multiplexing, the select or poll function can be called, blocking on one of these two system calls, instead of blocking on the actual I/O system call.

    This is blocked on the select call. When select returns the condition that the socket can be read, recvfrom is called to copy the read datagram to the application process buffer. Compared with blocking I/O, since using select requires two system calls, it seems that I/O multiplexing has a slight disadvantage. But the advantage of using select is that you can wait for multiple descriptors to be ready. Another I/O model that is very similar to this model is using blocking I/O in multithreading, but instead of using select to block on multiple file descriptors, it uses multiple threads (each file descriptor one thread), each thread is free to call blocking I/O system calls such as recvfrom.
    Signal-driven I/O is to let the kernel send a SIGIO signal to notify us when the descriptor is ready.

    First, the signal-driven I/O function of the socket is enabled, and a signal processing function is installed through the sigaction system call, and then the system call returns immediately, and the process continues to work. When the datagram is ready to be read, the kernel generates a SIGIO signal for the process, then recvfrom can be called in the signal handler to read the datagram and notify the main loop that the data is ready for processing, or immediately notify the main loop , so that it reads the datagram.
    The mechanism at work in the asynchronous I/O model is: tell the kernel to start an operation, and have the kernel notify us when the entire operation (including copying data from the kernel to the buffer) is complete. The main difference between this model and the signal-driven model is that the signal-driven model tells us when an I/O operation can be started by the kernel, while the asynchronous I/O model tells us when the I/O operation is complete.

    This calls the aio_read function (POSIX asynchronous I/O functions start with aio_ or lio_) to pass the descriptor, buffer pointer, buffer size (same three parameters as read) and file offset to the kernel, and tell the kernel when the entire operation How to notify us when it's done. The system call returns immediately, and the process does not block while waiting for the I/O to complete.
    The difference between these five I/O models is shown in the figure below.

    The terms synchronous I/O and asynchronous I/O are defined in POSIX as follows:
    * A synchronous I/O operation causes the requesting process to block until the I/O operation completes.
    * Asynchronous I/O operations do not cause the requesting process to block.
    According to this definition, it can be seen that the first 4 I/O models are all synchronous I/O models, because the real I/O operation blocks the process, and only the asynchronous I/O model matches the asynchronous I/O defined by POSIX.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326211076&siteId=291194637