1.C Standard library I/O buffers
UNIX is a traditional everything is a file, keyboard, monitor, serial, disk and other devices in the/dev directory has a special device files corresponding to, these device files can also be like a normal file (saved on the disk) as open, read, write and shutdown, The function interfaces used are the same. The user program invokes the C standard I/O library function to read and write normal files or devices, and these library functions pass the read and write requests to the kernel through system calls, and eventually the kernel drives the disk or device to complete I/O operations. The C standard library allocates an I/O buffer for each open file to speed up the read and write operation, which can be found through the file structure of files, where the user invokes the read-write function and reads and writes most of the I/O buffer, and only a few times needs to pass the read-write request to the Taking FGETC/FPUTC as an example, when the user program first calls Fgetc to read a byte, the FGETC function may enter the kernel through the system call into the core read 1K bytes into the I/O buffer, and then return the first byte in the I/O buffer to the user, pointing the read-write position to the i/ The second character in the O buffer, which is then read directly from the I/O buffer, without the need to enter the kernel, and when the user reads the 1K bytes and calls Fgetc again, the FGETC function enters the kernel read 1K bytes into the I/O buffer again fgetc. In this scenario, the user program, the relationship between the C standard library and the kernel is like the relationship between CPU, cache, and memory in "Memory hierarchy", where the C standard library reads some data from the kernel into the I/O buffer, expecting the user program to use the data later. The C standard Library's I/O buffers are also in user space, and reading data directly from the user space is much faster than reading data into the kernel. On the other hand, the user program invocation FPUTC is usually written to the I/O buffer so that the FPUTC function can quickly return, and if the I/O buffer is full, FPUTC passes the data in the I/O buffer to the kernel through system calls, which eventually writes the data back to the disk or device. Sometimes the user program wants to pass the data in the I/O buffer to the kernel immediately, let the kernel write back to the device or disk, which is called the flush operation, and the corresponding library function is the Fflush,fclose function will do flush operation before closing the file.
We know that the main function is called by the startup code: Exit (Main (ARGC, argv));
The startup code calls exit when the main function return, the Exit function first closes all file * pointers that have not been closed (flush before closing), and then exits the current process by _exit system calls into the kernel.
There are three types of I/O buffers for the C standard library: Full buffering, row buffering, and no buffering. When a user program calls a library function to write, different types of buffers have different attributes.
Full buffer
If the buffer is full, write back to the kernel. Regular files are usually fully buffered.
Row buffering
Write the line back to the kernel if the user program writes a newline character, or write back the kernel if the buffer is full. Standard input and standard output are usually line buffers when they correspond to terminal devices.
No buffer
The user program writes every time the library function writes to the kernel through the system call. The standard error output is usually not buffered so that the error messages generated by the user program can be exported to the device as quickly as possible.
In addition to writing full buffers and writing line breaks, there are two things that can be done flush automatically by the line buffer. If:
User Program call library function read from no buffered file
Or read from a row-buffered file, and this read will cause system calls to read data from the kernel
If the user program does not want to rely entirely on automatic flush operations, you can adjust the Fflush function to do flush operations manually.
#include <stdio.h>
int fflush (FILE *stream);
Return value: Successfully returned 0, error returns EOF and sets errno
The Fflush function is used to ensure that the data is written back to the kernel to avoid losing data when the process terminates abnormally, such as fflush (stdout); As a special case, calling Fflush (NULL) can flush the I/O buffers of all open files.