1

I have the following code:

int main(){
  int i = 4, pid;
  while (--i){
    pid = fork();
    if (pid || (i&1))
      printf ("Boo %d\n", i);
  }
  return 0;
}

I understand the code, but I don't understand why I get different results when I run the code multiple times.

Can someone show me how the scheduling can be different?

Mickey
  • 480
  • 4
  • 13

2 Answers2

2

After the fork(), the process (child or parent) which runs next is essentially random. The if is true for all parent processes and half the child processes.

The randomness persists for each child when it becomes a parent.

Boo 3
Boo 3
Boo 2
Boo 2
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1

This seems pretty logical. But on another run, I got this:

Boo 3
Boo 2
Boo 1
Boo 3
Boo 2
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1
Boo 1

In this case, one of the first processes didn't get to run until after a great ancestor of the other.

There is no predictability to process scheduling. That is simply the nature of operating systems. If you need some sort of sequence control, extra code must be added. Perhaps some timers, or mutexes, or master scheduling.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • Yes, that's exactly the results I got and didn't understand why it can happen. But why replacing the || with && avoid this? In this case it's always 3,1,1,1 (2 of course cannot happen). Why in this case the outputs are always the same? – Mickey Jun 16 '14 at 04:51
  • @user3699365: Perhaps the computer has only one CPU and one core, so there is little chance of random scheduling. My computer has four cores, so that throws some wrinkles into the sequence. – wallyk Jun 16 '14 at 05:00
0

You have to understand that printf is extremely slow compared to the rest of the program, and printf internals only execute one processes at a time - with the others waiting to get access to the console. This means that the print order could really by anything.

Try printing something before you fork. This means the process cannot fork until it is assured of having its output on the screen. In your case the whole tree of processes could all be running at once before even a single printf has completed, with all of them waiting for the console. The operating system and printf implementation could decide which one goes first on a huge number of factors - usually not the process ID, so their execution of printf appears random.

You need to use semaphores if you want to ensure order of execution, by passing a semaphore from one thread to the next when it is their turn.

Myforwik
  • 3,438
  • 5
  • 35
  • 42
  • `fork()` does *not* cause `printf` to flush its buffer. See [this question](http://stackoverflow.com/q/11132868/198536). Also, there is no console locking or contention on Linux/Unix. As soon as `printf` flushes its buffer, the characters appear on the console, possibly interrupting other output. – wallyk Jun 16 '14 at 15:10