2

So I have the following C code:

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

int main(){
    int i = 0, n;
    n = 5;
    pid_t pid;
    printf("i=%d Right before the loop\n", i, getpid(), getppid());
    for (i = 0; i < n; i++){
        pid = fork();
        if (pid <= 0){
            printf("something happens in loop #%d. pid = %d\n", i, pid);
            break;
        }
        printf("End of loop #%d\n", i);
    }

    printf("i=%d My process ID = %d and my parent's ID = %d\n", i, getpid(), getppid());

    return 0;
}

I have only one question: Why does

printf("i=%d My process ID = %d and my parent's ID = %d\n", i, getpid(), getppid());

get executed many times as if it was inside the loop? I have tried to figure out through so many ways but I cannot find the reason.

SusanW
  • 1,550
  • 1
  • 12
  • 22
Ren
  • 4,594
  • 9
  • 33
  • 61
  • The question is how do you compile and run this code? Although, yes, it does seem very weird... Looking forward to see the answer. – sashkello Sep 20 '13 at 01:41
  • I am using geany in Ubuntu and compiling/running it through the terminal. something along the lines of `cgg -W main.c -o mainProgram` to compile it and `./mainProgram` to run it once it compiled fine. – Ren Sep 20 '13 at 01:43

2 Answers2

6

The reason is that fork() works by making a child process that is a copy of the parent that starts running at the fork() call. So every child process runs that printf command.

Example:

Here's a less complicated example:

#include <stdio.h>

int main(){
  int pid = fork();

  if (pid == 0){
    // child code    
    printf("child pid: 0\n");

  }else{
    // parent code
    printf("parent pid: %d\n", pid);
  }

  // executed by both
  printf("This text brought to you by process %d.\n", pid);
}

You have to do something like this if you want to restrict some code to only be run by the child or parent.

On my machine, when I just ran it, it outputs:

parent pid: 12513
This text brought to you by process 12513.
child pid: 0
This text brought to you by process 0.

My operating system ran the parent process first, but it didn't have to.

Matthew Adams
  • 9,426
  • 3
  • 27
  • 43
  • I see, that might also explain why stuff is often printed so out of order. I assume it's because the processes run at the same time? – Ren Sep 20 '13 at 01:46
  • Well sort of at the same time. It's up to the operating system to choose what order to run the processes in and when to switch between running them. Your results actually show what order everything's being run it. – Matthew Adams Sep 20 '13 at 01:51
  • It's important that you can't rely on the processes being executed in a specific order. This is one reason why concurrent programming is so difficult. – Matthew Adams Sep 20 '13 at 02:00
  • Well, from what I've learned so far is that in multiprocessing systems processes happen simultaneously, one taking over the io, while the other takes over the processing unit (putting it in a simple way, that is). That is basically what I was trying to say. Not sure if that is what is happening in this case or not. I've spent hours trying to figure that out. – Ren Sep 20 '13 at 02:14
  • Technically we're talking about "multiprogramming" ("[multiprocessing](http://en.wikipedia.org/wiki/Multiprocessing)" is referring to using multiple processors), but yeah on a single-processor system, the OS decides when one process (whether it was forked from another process or not) is run as opposed to another, and a good basic strategy is to run one process while the other's waiting on I/O. This scheduling happens for every process. Hope that clarifies things a bit. – Matthew Adams Sep 20 '13 at 02:25
  • Yes, I understood that to a 95%, thank you. And sorry about the term confusion ^_^ – Ren Sep 20 '13 at 02:44
1

If you are not aware of fork() and using it, it is dangerous.

This is one of the basic system calls in Linux used for creating a new process. Refer to Man page to know what it does. And here is one helpful link to make you understand better. fork(). To know more about it you could also refer here- fork() wiki. It uses methods like copy-on-write and shares the resources with child.

Once you have used fork() to create the new process, you can use exec(...) to change the program that the process is executing. After reading about each of them, you may refer to this post on so.

Community
  • 1
  • 1
Sandeep
  • 18,356
  • 16
  • 68
  • 108
  • thank you. Unfortunately, my homework is all about getting familiar with this mr. fork() so there is no escaping. I am being as careful as I can however and definitely read your sources. – Ren Sep 20 '13 at 02:11
  • Ok so how did you come across this program? You used it as it is from some source and trying to understand what it is? If it is the case, probably that is not the right way. Refer to the man page and explanations in your text and try to use it on your own in a fresh program written by you. This way you will understand the program you are going to compile.. – Sandeep Sep 20 '13 at 02:16
  • It was an example given in class that I modified on my own with a lot more `printf()`'s and a few other things so I could see what was going on. And yes, just did. thanks a lot sir. – Ren Sep 20 '13 at 02:45