Home > Blockchain >  C - fdopen gives a stream for STDOUT_FILENO that doesn't work with fflush
C - fdopen gives a stream for STDOUT_FILENO that doesn't work with fflush

Time:09-04

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.

  • Related