#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().
时间: 2024-10-26 23:51:54