3

I'm trying to understand how fork works, and I know that when you call fork() another process is created that resumes from the exact same line with the heap and stack copied to it. For the parent, fork() returns the PID of the child and for the child it returns 0.

I stumbled across this question: "How many processes does the following sequence create?"

fork();fork();wait(0);fork();wait(0);

The answer is 8, including the parent, but I do not clearly understand if wait(0) actually waits or not. I found this related to the manual of "wait":

If there are at least one child processes running when the call to wait() is made, the caller will be blocked until one of its child processes exits. At that moment, the caller resumes its execution. If there is no child process running when the call to wait() is made, then this wait() has no effect at all. That is, it is as if no wait() is there.

My understanding of this can be drawn as such:

enter image description here

Where the leftmost branch is the parent and the black circles are where forks were made. This makes me believe that the wait(0)'s do nothing because there are no children to wait for, so it's simply ignored. However, i made a little modification to the code, adding an "index" to each process.

#include <stdio.h>
int main()
{

    int index = 0;
    if (fork()==0)
    index++;
    if (fork()==0)
    index++;
    wait(0);
    if (fork()==0)
    index++;
    wait(0); 
    printf("%d\n",index);
}

And this prints out 21312021

After commenting the wait(0)'s out, so the code is:

#include <stdio.h>
int main()
{

    int index = 0;
    if (fork()==0)
    index++;
    if (fork()==0)
    index++;
    if (fork()==0)
    index++;
    printf("%d\n",index);
}

It prints out 0112223, so something is clearly different. Why are the results different?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
KiralyCraft
  • 109
  • 5
  • 16
  • 3
    very well explained and tested question. – Gabri T Jun 12 '17 at 09:51
  • 3
    There *are* children to wait for because all the parent processes execute the same `wait(0)` ... –  Jun 12 '17 at 09:52
  • I think i understand now, due to how my drawing was done, it excludes the fact that parents from the "middle generation" also wait. Is that correct? – KiralyCraft Jun 12 '17 at 10:01
  • 1
    The `wait(0)` calls will affect how many processes run simultaneously. But all processes run the same sequence that includes 3 `fork()` calls, so there are are 8 processes in total. You could argue that the number of processes created by the sequence is actually 7, since one process has to be running before the start of the sequence and the other 7 are created by the sequence itself. – Ian Abbott Jun 12 '17 at 10:08

2 Answers2

4

I can't see your image, but here's one that should exactly reflect the runtime behavior of this program. Adding explicit exit(0) calls helps a bit with the understanding:

fork() ----------------------------,
  |                                |
fork() -----,                    fork() -------,
  |         |                      |           |
  |       wait(0)                  |         wait(0)
  |         |                      |           |
  |       fork()------,            |         fork() ------, 
  |         |         |            |           |          |
  |         |       wait(0)        |           |        wait(0)
  |         |         |            |           |          |
  |         |       exit(0)        |           |        exit(0)
  |         |         |            |           |          | 
  |       wait(0) <---´            |         wait(0) <----´
  |         |                      |           |
  |       exit(0)                  |         exit(0)
  |         |                      |           |
  |         |                    wait(0) <-----´
  |         |                      |
  |         |                    fork() -------,
  |         |                      |           |
  |         |                      |         wait(0)
  |         |                      |           |
  |         |                      |         exit(0)
  |         |                      |           |
  |         |                    wait(0) <-----´
  |         |                      |
  |         |                    exit(0)
  |         |                      |
wait(0) <---+----------------------´
  |
fork()------,
  |         |
  |       wait(0)
  |         |
  |       exit(0)
  |         |
wait(0) <---´
  |
exit(0)

here, each child process is drawn to the right of the parent process. Each wait(0) will wait for those lines that emerged from a fork() above.

One thing can't be shown exactly: the first process at its first wait() is in a position where 2 child processes are running, so it will wait for whichever finishes first. The + in my picture is to be understood as an either or (and I can't think of a better way to show this graphically).

  • This finally cleared it all out. It really makes sense now. Thanks for your time making the ascii diagram <3 – KiralyCraft Jun 12 '17 at 10:22
  • @KiralyCraft YW, I just added some details at the one point where the diagram could be a bit misleading. –  Jun 12 '17 at 10:27
2

wait(0) will block parent process until any of its children has finished and there exist children to wait for because all the parent processes execute the same wait(0) (a child that forks, becomes a parent of the new child).

gsamaras
  • 71,951
  • 46
  • 188
  • 305