1. Introduction
A stream based operation will eventually invoke the read or write function for I/O operations. In order for the program to run most efficiently, the stream object usually provides a buffer to reduce the number of calls to the system I/O library function.
In Linux, there are three ways to buffer, respectively:
(1) Full buffer. The input or output buffers are filled and actual I/O operations are performed. Other situations, such as forced flushes, and the end of the process, also perform actual I/O operations.
For read operations, when the number of bytes read is equal to the buffer size or the file has reached the end, or forced to flush, the actual I/O operation is performed, the contents of the external memory file are read into the buffer, and for write operations, actual I/O is performed when the buffer is filled or forced to The buffer contents are written to the external memory file. Disk file operations are usually fully buffered.
(2) Line buffering. The input or output buffer encounters a newline character for actual I/O operations. The other is the same as the full buffer.
(3) No buffer. Without buffers, the data is immediately read into memory or exported to the external storage files and devices. Standard error output stderr is not buffered, so that the error message can be timely feedback to the user, for users to troubleshoot errors.
Three types of buffered macros are defined in header file <stdio.h>.
Buffer Type |
Macros |
Full buffer |
_iofbf |
Row buffering |
_iolbf |
No buffer |
_ionbf |
In the learning Apue this book, in program 8-1, it is very good to reflect the total buffer and row buffer difference, the code is as follows:
#include <stdio.h>
#include <stdlib.h>
int glob=6;
int main (int argc, char** argv) {
int var;
pid_t pid;
printf ("A write to stdout\n");
if (Pid=fork () <0) {
printf ("fork Error");
} else{
if (pid==0) {
glob++;
var++;
}
else{Sleep
(2);
}
}
printf ("pid=%d,glob=%d,var=%d\n", Getpid (), glob,var);
Exit (0);
}
After compiling successfully, the binary file I generated here defaults to a.out, and the results are as follows:
./a.out
A write to stdout
pid=4823,glob=7,var=4195873
pid=4824,glob=7,var=4195873
./a.out > Temp.txt
Cat Temp.txt
A write to stdout
pid=4864,glob=7,var=4195873
A write to stdout
pid= 4865,glob=7,var=4195873
Visible printf is a row buffer when output to standard output (monitor), output the buffer contents to the monitor when a newline character is encountered, and empties the buffer. When the redirect command is used, the standard output is redirected to the disk file, at which point the standard output becomes full buffering, the line breaks are not output, but is copied to the subprocess, and each has an output after the parent-child process is finished. 2. Buffer Settings
(1) Set whether to open the buffer, you can use the function setbuf or SetBuffer. The SETBUF and SetBuffer functions have an open and close buffering mechanism. For I/O with buffering, the parameter buf points to the buffer. Usually after this the stream is fully buffered, but if the stream is related to a terminal device, some systems can also set it as a row buffer. To turn off buffering, you can set the BUF parameter to NULL. note that the SetBuffer () non-C standard library functions are found in the BSD system.
The buffer length for setbuf () must be bufsiz (defined in stdio.h), otherwise a buffer overflow may occur. SetBuffer can specify the buffer size.
@header: stdio.h
//@brief: Set the specified buffer or turn off buffering
//@param: stream: File pointer; buffer: Buffers address
//@notice: Use default buffer size Bufsiz (defined in stdio.h)
void setbuf (FILE * stream, char * buffer);
@notice: Same setbuf, but can specify buffer size
void SetBuffer (FILE *stream, char *buf, size_t size);
Specifies that buffer is null and the standard output buffer is turned off.
Setbuf (Stdout,null)
Specifies a new buffer.
The static char newbuffer[bufsiz];//must be bufsiz (defined in stdio.h), otherwise there might be buffer overflow
setbuf (stdout, (char*) &newbuffer);
or specify buffer size
static char newbuffer[512];
SetBuffer (stdout, (char*) &newbuffer,512);
(2) Change the buffering mode, you can use the function setvbuf.
@header: stdio.h
//@brief: Change buffering mode and set buffer
//@param: stream: file pointer; buf buffer address; type: buffer mode; size: Buffer size
//@ret : 0 successful, non 0 failed
int setvbuf (FILE *stream, char *buf, int type, unsigned size);
For example, the stream buffer is set to row buffering, and when Setvbuf is invoked, the buffer address is set to null and the buffer size is set to 0. note that the premise is that there is a buffer.
Setvbuf (stream,null,_iolbf,0); Measured in VS2015, the size needs to be greater than 0, and can only be set to full buffer
//above code equivalent to
setlinebuf (stream); For BSD
If the call setvbuf specifies that the buffer size is greater than 0 and the buffer buf is null, the SETVBUF is malloc the request buffer.
Indirect request 1024 byte full buffer
setvbuf (stream, NULL, _IOFBF, 1024);//tested Linux is invalid, VS2015 can set buffer size
//below in Windows and Linux are valid, Display indicates full buffer
static char buf[1024];
Setvbuf (stream, buff, _IOFBF, 1024);
For the above functions, Linux and Windows platform for the specific implementation of SETVBUF () is not the same, when used, please note that, summed up the following points:
(1) Linux platform to the device file to open the default line buffer, the disk file to open the default full buffer.
Turn off buffer with setbuf (). In the presence of buffer, change the buffering mode with SETVBUF (). Note that you cannot use SETVBUF () to indirectly request a buffer, only the indicated buffer.
When there is no buffer, the indirect request buffer is invalid
setvbuf (stdout,null,_iofbf,100);
can display a specified buffer
static char buf[100];
Setvbuf (stdout, buf,_iofbf,100);
(2) Windows defaults to turn off buffering, can only open full buffer, the opening mode is as follows:
static Char buf[100];
Setbuf (STDOUT,BUF); Unsafe, do not recommend
the use of setvbuf (stdout, buf,_iofbf,100);
Indirect application buffer
setvbuf (stdout,null,_iofbf,100);
reference materials
[1]setvbuf