matzel
matzel

Reputation: 3

Why is the output of a fork() in a particular order?

I am doing some Operating System 101 homework and digging through some C code.

I am new to C and Linux so i have this maybe unusual question. I had to examine a C program to figure out, how many processes it starts. So I read a lot and tinkered with the original code to answer the all the questions.

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
   printf("Start ID %d\n\n", getpid());

   printf("1.fork() from ");   
   printf("ID: %d\n", getpid());
   fflush(stdout);
   fork();

   printf("2.fork() from ");
   printf("ID: %d my parent is ID %d\n", getpid(), getppid());   
   fflush(stdout);
   fork();

   printf("3.fork() from ");
   printf("ID: %d my parent is ID %d\n", getpid(), getppid());  
   fflush(stdout);
   fork();

   sleep(2);   
   printf("%d finished. Good Night!\n", getpid());
   return EXIT_SUCCESS;
}

There is one thing I don't understand. Why are the outputs of printf() before the forks in this order:

1.fork() from ID: 3124
2.fork() from ID: 3124 my parent is ID 2215
3.fork() from ID: 3124 my parent is ID 2215
3.fork() from ID: 3126 my parent is ID 3124
2.fork() from ID: 3125 my parent is ID 3124
3.fork() from ID: 3125 my parent is ID 3124
3.fork() from ID: 3129 my parent is ID 3125

I would expect

1.fork() from ID: 3124
2.fork() from ID: 3124 my parent is ID 2215
3.fork() from ID: 3124 my parent is ID 2215
2.fork() from ID: 3125 my parent is ID 3124
3.fork() from ID: 3125 my parent is ID 3124
3.fork() from ID: 3126 my parent is ID 3124 
3.fork() from ID: 3125 my parent is ID 3124
3.fork() from ID: 3129 my parent is ID 3125

because PID 3124 starts PID 3125 with the first fork(), both another two child processes with the second and so on. Does the CPU not execute the processes in the order the have been created? This is not part of my homework, but I am still curious about it.

Upvotes: 0

Views: 1054

Answers (2)

Alexander James Pane
Alexander James Pane

Reputation: 648

You can't really determine which process will be executed first. Like HackerBoss stated the printf can also influence this order.

Imagine your main program pid (3124) generates child 3125. After generating the child the following instruction needs to be invoked by both father and child:

printf("2.fork() from ");

At this point there are two directions:

  1. Fater 3124 invokes the printf
  2. Child 3125 invokes the printf

Since the printf requires I/O scheduling it depends on the process priority and on the resource state (there could be another process already already using the resource, making it a busy resource).

So it looks like in your program the father 3124 gets access to the resource first and continues executing up to the next fork, where child 3126 gets generated.

At this point there is the same question: in which direction shall I go? The next instruction is:

printf("3.fork() from ");

Directions are:

  1. Fater 3124 invokes the printf
  2. Child 3126 invokes the printf

From your program it looks like the first process to invoke it is child 3126.

So actually the printf does not assure you the process generation order. Since it is transparent how the I/O scheduling works, a better way would be to store a value in a specific address different for each process, by wrapping the fork in a if statement:

pid=fork();
if (pid == 0) {
    //child process
} else {
    //father process
}

This way you can have a better idea on what the process scheduler is doing, since it could actually be the process scheduler that starts a child before another, there are a lot of scheduling algorithms. At this point the OS you are running also influences the process execution order, depending on the used algorithm.

Upvotes: 1

HackerBoss
HackerBoss

Reputation: 829

The output of the printf statements can vary from run to run, since one forked process may finish faster than another. In these cases, it is helpful to draw a fork tree diagram to determine all of the possible cases. In your case, you can only guarantee that the first print statement will print first, the second print statement will print before the third print statement within the same fork, and the second print statement will print before the third print statement in the second forked child. This gives several possible outputs. Technically, it is possible that one process would not finish in 2 seconds and would print its output after one of the finish statements, although this is unlikely.

P.S. It is good practice to wrap fork in an if to check for system errors, but it will usually work.

Upvotes: 0

Related Questions