FourOfAKind
FourOfAKind

Reputation: 2418

Statement with multiple fork() s

The child process begins executing at the exact point where the last one left off - after the fork statement. What if the statement contains multiple fork()s like the conditional expression like the following. Where exactly program execution starts for the child process. Before worrying about how many processes gets created, I wanted to know if every child process created tries to evaluate fork() && fork() || fork(); statement. If it is so. How does a child process that got created because of second fork() statement have information from the first fork() to evaluate fork() && fork().

main(){
fork() && fork() || fork();
}

Upvotes: 2

Views: 1561

Answers (3)

Carl Norum
Carl Norum

Reputation: 224884

The child that results from the second fork() knows about the results of the first fork() because it is an exact copy of the parent process.

You can work out what happens by drawing a little tree for yourself. Start with the first fork:

         fork()
           /\
          /  \
parent --/    \-- child1

The parent gets back the PID of the child1 process, and child1 gets back 0. So we have something like:

PID(child1) && fork() || fork()

in the parent, and:

0 && fork() || fork()

in the child. Short circuiting means that the middle fork() of the original expression doesn't get executed in the child, only in the parent. So now what happens to the tree?

                  fork()
                    /\
                   /  \
         parent --/    \-- child1
         fork()
           /\
          /  \
parent --/    \-- child2

parent is the original process, and gets the PID of child2. child2, just like child1, gets 0. What do our expressions look like now?

parent:  PID(child1) && PID(child2) || fork() = 1 || fork()
child:   0 || fork()
child2:  PID(child1) && 0 || fork() = 0 || fork()

Now, again by short-circuiting, parent is done, and doesn't execute the last fork(). Both child and child2 have to, however. That leaves us with the following tree:

                     fork()
                       /\
                      /  \
            parent --/    \-- child1
            fork()            fork()
              /\                /\
             /  \              /  \
            /    \   child1 --/    \-- child1-1
           /      \
          /        \
parent --/          \-- child2
                        fork()
                          /\
                         /  \
               child2 --/    \-- child2-1

And that's it. child1 and child2 each get the PID of their respective children, and child1-1 and child2-1 each get back 0. Substituting those values in, the final expressions are:

parent:   1
child1:   0 || PID(child1-1) = 1
child2:   0 || PID(child2-1) = 1
child1-1: 0 || 0 = 0
child2-1: 0 || 0 = 0

And that's it - they all exit.

Upvotes: 7

user257111
user257111

Reputation:

fork() && fork() 

Is equivalent to writing:

pid_t x = fork();
if ( x > 0 )
{
    fork();
}

That is, the parent process will fork twice, since both conditions are evaluated; neither child will fork() since both return 0 from the fork. However, fork() || fork () is equivalent to:

pid_t x = fork();
if ( x == 0 )
{
    fork();
}

So, the parent process will fork() once and its child will fork() once.

If you speak asm, try spitting out the output from these two expressions:

movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    call    fork
    testl   %eax, %eax
    je  .L3         // jump if eax is zero
    call    fork
    testl   %eax, %eax
    nop
.L3:
    call    fork
    testl   %eax, %eax
    jne .L7         // jump if eax is non-zero.
    call    fork
    testl   %eax, %eax

Note that call fork is the point at which your process loses control and then regains it with eax set to the return value. This question will help understand testl.

You should be able to work out what would happen in your combined example using the operator precedence rules.

Upvotes: 1

David Schwartz
David Schwartz

Reputation: 182763

I'm not sure what could be confusing. When the fork function is called, it creates a second process that is a duplicate of the existing process. Both processes continue from precisely where they left off. The child knows how to continue evaluating the same way the parent does because it has precisely the information it needs in precisely the place it needs it because it is a clone.

Upvotes: 1

Related Questions