I have a C programme like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("hello world (pid:%d)\n", (int)getpid());
int rc = fork();
if (rc < 0)
{ // fork failed; exit
fprintf(stderr, "fork failed\n");
exit(1);
}
else if (rc == 0)
{ // child (new process)
printf("hello, I am child (pid:%d)\n", (int)getpid());
}
else
{ // parent goes down this path (main)
printf("hello, I am parent of %d (pid:%d)\n",
rc, (int)getpid());
}
return 0;
}
After finishing the gcc compilation, I got the "a.out" executable file. And I got the correct programme output in the Linux shell.
hello world (pid:1056088)
hello, I am parent of 1056089 (pid:1056088)
hello, I am child (pid:1056089)
But if I use the watch command to execute it, I got the output like this:
hello world (pid:1056155)
hello, I am parent of 1056156 (pid:1056155)
hello world (pid:1056155)
hello, I am child (pid:1056156)
I don't know why if I use the watch command, there would be an extra line in the output.
I have tried to delete the line "printf("hello world (pid:%d)\n", (int)getpid());", there would be no difference between the outputs. And if I add the "fflush(stdout);" line under it, it also has no difference between the outputs.
I would be appreciate if anybody can explain it to me.
CodePudding user response:
When printing to a pipe, standard output is buffered. When you fork, the whole program is copied to the fork, including the contents of the buffer.
If you print more than just one line, you can see that only the final part of it gets copied and printed twice, e.g.
for (int i = 1; i < 64000; i) printf("%d\n", i);
On my machine, everyting up to 63970 gets printed once, the rest is printed twice:
a.out | grep 6397[01]
63970
63971
63971
See also Why does printf not flush after the call unless a newline is in the format string?
CodePudding user response:
Thats because all definitions are transferred to beginning of your program by the C compiler so obviously both processes run the following line:
printf("hello world (pid:%d)\n", (int)getpid());
The reason ./a.out doesn't print it twice is related to flushing the output stream. so if you remove the \n character from this printf you see hello world printed twice on either of the commands.