When I run the following C code on a Linux system:
printf("This is sentence 1. ");
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
I get the output in a wrong order:
This is sentence 2.
This is sentence 1.
I understand that this happens because 'printf' sends the data to a buffer in the user space, and it takes some time to get to the kernel space, while 'write' sends the data immediately to the cache buffer in the kernel space.
A way to fix this is by flushing the data from user-space buffer to kernel-space buffer this way:
printf("This is sentence 1. ");
fflush(stdout);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
And then the correct output is received:
This is sentence 1. This is sentence 2.
Another way that I tried to solve this issue is by trying to get the stdout stream from the STDOUT_FILENO fd:
FILE *file = fdopen(STDOUT_FILENO, "w");
printf("This is sentence 1. ");
fflush(file);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
But, I get the output in the wrong order:
This is sentence 2.
This is sentence 1.
In order to make sure that STDOUT_FILENO is a fd that represents stdout, I converted stdout to a fd:
int fd = fileno(stdout);
if(fd == STDOUT_FILENO)
printf("fd == STDOUT_FILENO == %d\n", fd);
And received the expected output:
fd == STDOUT_FILENO == 1
So, the question is why when converting STDOUT_FILENO to a stream that should be equivalent to stdout, the 'fflush' function doesn't work? Is there a problem with the way I use 'fdopen'?
CodePudding user response:
The buffer is a property of the stdio stream, that is, the FILE
structure. printf
is always printing to stdout
, so it's the stdout
stream you need to call fflush
on. When you wrote
FILE *file = fdopen(STDOUT_FILENO, "w");`
, that gave you a second, completely independent FILE
stream, with its own buffer. But you don't print anything to that stream, so falling fflush
on it accomplishes nothing, and meanwhile, the text you printfed to stdout
remains unflushed.
If you've got buffered output on stdout
, it's stdout
you must call fflush
on. (Or, alternatively, add a \n
at the end of the string you print with printf
, since stdout
is typically line-buffered, at least if it's going to a terminal.)
CodePudding user response:
In this:
FILE *file = fdopen(STDOUT_FILENO, "w");
printf("This is sentence 1. ");
fflush(file);
write(STDOUT_FILENO, "This is sentence 2.\n", 20);
printf
does not send anything to file
. It writes to stdout
.
Each FILE
object contains its own buffer (whether directly or via pointer to allocated memory). When you execute printf("This is sentence 1. ");
, it writes to the buffer in the stdout
FILE
. When you fflush(file);
, it flushes the buffer in file
.
To make this work, you could write fprintf(file, "This is sentence 1. ");
, since that will write to the buffer in file
, and fflush(file);
will flush it.