2

I've seen lots of examples of forking in for loops on here, but not much clarification on how it does what it does. Lets use this simple example from an answer of How to use Fork() to create only 2 child processes? as an example.

for (i = 0; i < n; ++i) {
    pid = fork();
    if (pid) {
        continue;
    } else if (pid == 0) {
        break;
    } else {
        printf("fork error\n");
        exit(1);
    }
}

Most of the examples I've seen follow this general format. But what I don't understand is, how does this prevent child processes from forking as well? From my understanding, every child that gets created has to go through this loop as well. But fork() is called at the very beginning of the for loop, and then the 3 comparisons happen. Could someone explain how, even though the children seem to call fork(), this for loop still ensures only the parent can create children?

Community
  • 1
  • 1
Bob
  • 715
  • 2
  • 11
  • 32

5 Answers5

3

The child starts at the line after fork. fork returns 0 for the child. In your example, the child would go into the pid == 0 block and break out of the for loop.

After a fork everything is exactly the same for the child and parent (including the next instruction to execute and variable values). The only difference is the return value from fork (0 for the child, and the child's pid for the parent).

Riley
  • 698
  • 6
  • 11
  • Ohhh, thank you. I thought the child started at the very beginning of the program. – Bob Sep 23 '16 at 18:25
  • @Bob Nope. Everything is exactly the same (including the next instruction to execute and variable values). The only difference is the return from `fork`. – Riley Sep 23 '16 at 18:27
  • So fork doesn't immediately create a child when it's called? – Bob Sep 23 '16 at 18:33
  • @Bob It does. I meant that everything in the child and parent is exactly the same. When the return from the call to `fork` – Riley Sep 23 '16 at 18:35
  • But if the child starts from the beginning and has to go through the same for loop as its parent, that means it calls fork again right? So how does that not cause it to create another child? – Bob Sep 23 '16 at 18:45
  • @Bob It doesn't start from the beginning. The execution of the new (child) process starts at the instruction after the `fork`. Basically what happens when `fork` is called is the OS makes a bit for bit copy of the program (the memory values, register values, instruction pointer, everything) then sets the return value of the parent to the child's pid and the return value of the child to `0`. They are both then set to waiting so that the scheduler can run them on the cpu when it sees fit. – Riley Sep 23 '16 at 18:50
  • Oh okay I get it now. I misread one of your earlier replies. Thanks for the info! – Bob Sep 23 '16 at 19:13
2

When fork returns, it actually returns twice: once to the parent and once to the child. It returns 0 to the child and it returns the pid of the child to the parent.

The if block then detects which process returned. In the parent process, if (pid) evaluates to true, so it executes continue and jumps to the top of the loop.

In the child process, if (pid) evaluates to false, then if (pid == 0) evaluates to true, so it executes break to jump out of the loop. So the child doesn't do any more forking.

dbush
  • 205,898
  • 23
  • 218
  • 273
1

But what I don't understand is, how does this prevent child processes from forking as well?

fork() returns 0 in the child. In your example code, that causes the child to break out of the loop instead of performing another iteration, so the children in fact do not call fork().

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

After checking my Why does this program print “forked!” 4 times?. it seems straightforward to me why.

how does this prevent child processes from forking as well?

if (pid) {
  continue;
}

You see when the child is created, and then executes its code and calls fork() it becomes the parent in that stage, thus pid will be 0.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
0

Try man 2 fork. Fork(2) returns a different value for the parent and the child, the parent gets the pid and the child gets 0.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329