#include "light.h"
int main(int argc, char *argv[])
{
printf("Hello world\n");
write(STDOUT_FILENO, "Ciao\n", 5);
if (fork() == -1)
errExit("fork");
/* Both child and parent continue execution here */
exit(EXIT_SUCCESS);
}
When we run this program with standard output directed to the terminal, we see the expected result:
$ ./fork_stdio_buf
Hello world
Ciao
However, when we redirect standard output to a file, we see the following:
$ ./fork_stdio_buf > a
$ cat a
Ciao
Hello world
Hello world
Why?
recall that the stdio buffers are maintained in a process's user-space memory.
Therefore, these buffers are duplicated in the child by fork(). When standard out-put is
directed to a terminal, it is line-buffered by default, with the result that the newline-terminated
string written by printf() appears immediately. However, when standard output is directed to a
file, it is block-buffered by default. Thus, in our example, the string written by printf() is
still in the parent’s stdio buffer at the time of the fork(), and this string is duplicated in
the child. When the parent and the child later call exit(), they both flush their copies of the stdio
buffers, resulting in duplicate output.
We can prevent this duplicated output from occurring in one of the following ways:
As a specific solution to the stdio buffering issue, we can use fflush() to flush the
stdio buffer prior to a fork() call. Alternatively, we could use setvbuf() or setbuf()
to disable buffering on the stdio stream.
Instead of calling exit(), the child can call _exit(), so that it doesn’t flush stdio
buffers. This technique exemplifies a more general principle: in an application that creates
child processes, typically on ly one of the processes (most often the parent) should terminate
via exit(), while the other processes should terminate via _exit(). This ensures that only one
process calls exit handlers and flushes stdio buffers, which is usually desirable.
The output of the write() in the program doesn’t appear twice, because write() transfers data
directly to a kernel buffer, and this buffer is not dupli-cated during a fork(). By now, the reason
for the second strange aspect of the program’s output when redirected to a file should be clear.
The output of write() appears before that from printf() because the output of write() is immediately
transferred to the kernel buffer cache, while the output from printf() is transferred only when
the stdio buffers are flushed by the call to exit().
fork ,exit printf 的两次输出
最新推荐文章于 2023-05-19 23:40:40 发布