Buffered and non-buffered I/O, direct and indirect I/O, blocking and non-blocking I/O, synchronous and asynchronous I/O

Various differences in file reading and writing methods result in various I/O classifications. The most common are buffered and unbuffered I/O, direct and indirect I/O, blocking and non-blocking I/O, synchronous and asynchronous I/O.

According to whether the standard library cache is used or not, file I/O can be divided into buffered I/O and non-buffered I/O.

  • Buffered I/O refers to the use of standard library cache to speed up file access, and the standard library internally accesses files through system scheduling.

  • Unbuffered I/O refers to accessing files directly through system calls, and no longer passes through the standard library cache.

 The "buffer" mentioned here refers to the buffer implemented inside the standard library. For example, you may have seen that many programs actually output when they encounter a newline, and the content before the newline is actually temporarily cached by the standard library.

According to whether the page cache of the operating system is used, file I/O can be divided into direct I/O and indirect I/O.

  • Direct I/O refers to skip the page cache of the operating system and directly interact with the file system to access files.

  • Indirect I/O is just the opposite. When a file is read or written, it must pass through the page cache of the system, and then be called by the kernel or an additional system to actually write it to the disk.

To achieve direct I/O, you need to specify the O_DIRECT flag in the system call. If it is not set, the default is indirect I/O.

However, it should be noted that direct I/O and indirect I/O essentially interact with the file system. If it is in a database and other scenarios, you will also see that the file system is skipped to read and write to the disk, which is what we usually call bare I/O.

According to whether the application blocks itself, file I/O can be divided into blocking I/O and non-blocking I/O:

  • The so-called blocking I/O means that after the application performs an I/O operation, if it does not get a response, it will block the current thread and naturally cannot perform other tasks.

  • The so-called non-blocking I/O means that after the application performs an I/O operation, it will not block the current thread, and can continue to perform other tasks, and then obtain the result of the call through polling or event notification.

For example, when accessing pipes or network sockets, setting the O_NONBLOCK flag means accessing in non-blocking mode; and if you don't do any settings, the default is to block access.

According to whether to wait for the response result, file I/O can be divided into synchronous and asynchronous I/O:

  • The so-called synchronous I/O means that after the application performs an I/O operation, it has to wait until the entire I/O is completed to obtain an I/O response ( requires active reading and writing of data , such as read, write, etc.)

  • The so-called asynchronous I/O means that after the application performs an I/O operation, it does not need to wait for completion and the response after completion, but can continue to execute. After this I/O is completed, the response will use event notification to tell the application ( operating system to complete the reading and writing of data ).

For example, when operating files, if you set the O_SYNC or O_DSYNC flag, it means synchronous I/O. If O_DSYNC is set, you must wait for the file data to be written to the disk before returning; while O_SYNC is based on O_DSYNC and requires the file metadata to be written to the disk before returning.

For another example, when accessing a pipe or network socket, after setting the O_ASYNC option, the corresponding I/O is asynchronous I/O. In this way, the kernel will then notify the process whether the file is readable and writable through SIGIO or SIGPOLL.

We may ask the difference and connection between blocking and non-blocking I/O and synchronous and asynchronous I/O

Through the definition, it can be seen that blocking/non-blocking and synchronous/asynchronous are actually two different ways of dividing I/O. The objects they describe are also different. Blocking/non-blocking refers to the I/O caller (ie application), while synchronous/asynchronous refers to the I/O executor (ie system).

Knowing the answer of the great god teacher Chen Shuo:

When dealing with IO, both blocking and non-blocking are synchronous IO (the select/poll/epoll/read/write functions we use are all synchronous IO). Only when a special API is used is asynchronous IO.

Guess you like

Origin blog.csdn.net/u014608280/article/details/105492199