Fork () on linux

I tried to understand forks and tried to follow in C:

#include<stdio.h> #include <unistd.h> void forker() { printf("%d: A\n",(int)getpid()); fork(); wait(); printf("%d: B\n",(int)getpid()); printf("%d: C\n",(int)getpid()); fork(); wait(); printf("%d: D\n",(int)getpid()); } int main(void) { forker(); return 0; } 

When I compiled and ran the resulting a.out, here is what I noticed:

 > ./a.out 3560: A 3561: B 3561: C 3562: D 3561: D 3560: B 3560: C 3563: D 3560: D 

However, when I do the following:

 > ./a.out > t.txt 

something strange happens:

 > cat t.txt 3564: A 3565: B 3565: C 3566: D 3564: A 3565: B 3565: C 3565: D 3564: A 3564: B 3564: C 3567: D 3564: A 3564: B 3564: C 3564: D 

Can someone explain this behavior? Why is the output different when redirecting to a file?

I am using Ubuntu 10.10, gcc version 4.4.5.

+6
source share
3 answers

The reason for this is data buffering. During fork (), when accessing the file, your output has not yet been cleared ... so the parent and child now have outstanding output buffers.

Put a call to fflush(stdout); before each fork(); , to solve this problem.

+10
source

The problem is that printf output is passed through the library buffer before being sent to the file, which causes the strange behavior you were talking about. If you add fflush(stdout) after each printf , your output will be correct inside the file fflush(stdout) .

You can learn more about this here: http://www.pixelbeat.org/programming/stdio_buffering/

+3
source

Other answers do not exactly describe what is happening, and I had to think a little more to understand. Thus, in the second case (the output is buffered due to file redirection) and using 1,2,3 and 4 instead of 3564, 3565, 3566 and 3567:

  • process 1 prints "A: 1" in its internal stdout buffer;
  • fork process 1 and process 2 are created, this creation implies a copy of the stdout internal buffer, which has not yet been printed;
  • process 1 prints "B: 1" and "C: 1" in its internal stdout buffer, process 2 "B: 2" and "C: 2";
  • both fork processes (in your case 1-> 4 and 2-> 3, but it could be different), duplicating both internal buffers;
  • All 4 processes print line D in their buffers and then exit.

At this point, the contents of the 4 internal stdout buffers are:

 - process 1: A:1 B:1 C:1 D:1 - process 2: A:1 B:2 C:2 D:2 - process 3: A:1 B:2 C:2 D:3 - process 4: A:1 B:1 C:1 D:4 
  • Finally, 4 buffers are printed in a non-deterministic order. In your case, the order was 3, 2, 4, 1.

This behavior does not occur when stdout is a wrapper or with fflush() , because the stdout buffer is flushed before each fork() , so only empty buffers are duplicated.

+2
source

Source: https://habr.com/ru/post/902293/


All Articles