I just learned about file descriptors and I was trying some code to understand the way it works. When writing the following program I was expecting that the first printf should be written to the console, then since I close the standard output and open a new file, I expected it to return the smallest file descriptor which is 1 (since it is available because I closed it previously). Then I was expecting the second printf to write to the file file.txt.
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("before close");
close(1);
int x1 = open("./file.txt", O_RDWR);
printf("after close, the file descriptor is %d\n", x1);
}
However, when I execute this, nothing is printed to the console but everything is printed to the file.txt, i.e.
file.txt
before closeafter close, the file descriptor is 1
Why is that?
CodePudding user response:
It's a buffering issue.
Output to stdout
(which is where printf
writes) is buffered. When stdout
is connected to an interactive terminal then it's line buffered, which means the output is flushed (actually written) on newline.
So if you want the first output to be written to the console, add a newline to the output:
printf("before close\n");
As an alternative you could use fflush(stdout)
to explicitly flush the buffer. But note that since you don't print a newline, the output could seem to run into the shell prompt. Or the shell could print a special character to indicate the lack of newline, which could sometimes be confusing.
What is happening with your current code is that the output from the first printf
call stay in the buffer, and will be written when the second call leads to a flush of the buffer. By then the output will have been "redirected" to the file.
Note that the buffering is set before the main
function is called. Just because you change the destination for stdout
by closing and reopening the file descriptor doesn't mean the buffering will change. Your program will still be line buffered after the close
and open
calls.
If you want to change the buffering of stdout
you need to use the setvbuf
function.