-2

fork() calls outside a loop are easy to figure out, but when they are inside a loop I find it difficult. Can anyone figuratively explain how the processes branch out with an example like this one?

#include <stdio.h>

int main(){
    int i; 
    for(i=0;i<2;i++)
    {
        fork();
        printf("hi");
        fork();
    }
    exit(0);
}
Keith Thompson
  • 230,326
  • 38
  • 368
  • 578

3 Answers3

2

Ideally, this would be the case:

  • There is one "hi" printed with each process (abbreviated as proc)
  • Each fork doubles the number of process (each process spawns one child)

The calculation could be done by following each event:

  • start: 1 proc
  • fork: 2 x 1 = 2 procs
  • print: 2 procs -> 2 hi's
  • fork: 2 x 2 = 4 procs
  • fork: 2 x 4 = 8 procs
  • print: 8 procs -> 8 hi's
  • fork: 2 x 8 procs -> 16 procs

Now we add up the the number of hi's:

2 + 8 = 10 hi's in total

However, this is not necessarily the case. On different systems, you may get different results.

A call to fork() causes a child process to be spawned that is identical to the parent. If there is any buffering done when printing stdout and the buffers are not flushed before the next fork, then the child will appear to print when it "should not have". Refer to this question for some details on buffering.

This causes a different number of hi's to be printed an different systems.

Community
  • 1
  • 1
ryucl0ud
  • 542
  • 3
  • 7
1

Just unroll the loop:

int main() {
    int i;
    fork();
    printf("hi");
    fork();
    fork();
    printf("hi");
    fork();
    exit(0);
}
chepner
  • 389,128
  • 51
  • 403
  • 529
  • No. its not like that , by your explanation , there must be 16 "Hi"s but actually there are only 6 ... – wanttomasterpython Aug 10 '12 at 19:58
  • there are 12 http://ideone.com/bUNDZ note that there is to printf after the second fork in the loop – Gir Aug 10 '12 at 20:06
  • i am seeing inconsistent results http://ideone.com/QMesr http://ideone.com/gXVxW. could it be dur to exit(0) that kills child processes before they reached the print? – Gir Aug 10 '12 at 20:14
  • Actually, "hi" gets printed 32 times, which is easier to see if you redirect the output to a file. If you do, you may also see some null bytes. I suspect that it is not entirely safe to call `printf` after a fork (see the caveat at the end of `man printf`). Interestingly, I do not see the null bytes if I pipe the output into `hexdump`. – chepner Aug 10 '12 at 20:30
  • @Gir I am seeing the same behavior replacing `exit` with `return`. – chepner Aug 10 '12 at 20:31
  • 1
    i added fflush(0) after each printf and now get the expected 10 prints – Gir Aug 10 '12 at 20:34
  • Each process inherits the open file descriptors from its parent, which means all of the processes end up trying to write to the same file from `printf`; this is bound to be unpredictable. – chepner Aug 10 '12 at 20:35
  • Its not like that...I found out how to do. there are totally 4 fork()s .Lets see one by one . First fork,there are two processes , thus 2 his... second and third fork make the total no of processes as 8 processes , thus 8 more His... fourth fork doesnt affect us. thus total no of his is 2+8 = 10 ... – wanttomasterpython Sep 09 '12 at 04:10
0

I've used this code :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    int i; 
    for(i=0;i<2;i++)
    {
        fork();
        printf("hi from pid %d\n",getpid());
        fork();
    }
    exit(0);
}

Now i've piped the output to fk.out.

[aft@kruki sf]$ cat fk.out 
hi from pid 6698
hi from pid 6698
hi from pid 6699
.......................

Now look at this :

[aft@kruki sf]$ cat fk.out | awk '{print $4}' | sort | uniq | wc -l

8

There, you have it, you have 8 processes !. Don't coun't hi's. Because stdin buffer will switched back and forth, so counting hi's will be ambiguous.

Aftnix
  • 4,046
  • 5
  • 23
  • 41