working of fork in c language

Golu picture Golu · Jun 2, 2011 · Viewed 41k times · Source

Now I have a problem in understanding the working of fork() system call. I write a code which is following :

#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}

The output of this code is following :

Now I don't understand why the output is like this ?

After that i just add a line to my code and output is completely different. my code is following:

int main()
{
    int a, b;
    b=fork();

When i run the code the output is following 2389my name is manish

 the value of b = 0

Now I'm totally confused about the working of fork() call.

My question are following:

  1. How fork() works?
  2. Where the control goes after the fork() call?
  3. Can any body explain why the outputs of codes written in problem?
  4. Why the output of b occurring at different places means in first code the output of b = 2260 is just before the output b = 0 while the value of b = 2389 is not just before the b = 0?

Please explain me the working of fork in the code written in the problem so that I can learn it properly .

Answer

ladaghini picture ladaghini · Jun 2, 2011

It might help to first understand why the word fork was used to name this function. Ever heard of a "fork on the road?" At a fork, the process has to split paths.

First there is a single process executing normally until you reach the fork call. When fork is called, a new process is created, which is identical in virtually every way as the original process, except for the return value of the fork function. The newly created process is called the child process, and hence the process that spawned it is referred to as the parent process.

Since you'd want to perform different tasks for each branch of the fork, it necessitates that you be able to distinguish the child process from the parent process. That's where the return value of fork comes in: fork returns the process id (pid) of the child (the newly created process) to the parent; it returns 0 to the child. Also, should the execution of fork go wrong, the return value is -1.

In your code, you don't distinguish between the child and parent process, so both processes run the entire code that follows after the fork call.

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

As you can see, both processes have the same code following the fork, hence the output is repeated. Perhaps if you want the parent process to output Manish and the child to output Anil, then you can do something like:

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it's probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}

Finally, the last comment that must be made is that in your code, the output appears to have been executed first by one process in its entirety and then the other process in its entirety. That may not always be the case. For example, the operating system might allow the parent to execute the 'manish' output, then make this process wait, and handing the cpu over to the child process, which then executes 'manish'. However, the child process may continue and execute 'anil' and 'b' outputs, completing execution of the child process and thus returning execution back to the parent process. Now the parent finishes its execution by outputting 'anil' and 'b' itself. The final output of running this program may look something like:

my name is manish     // executed by parent
my name is anil       // child
the value of b = 0    // child
my name is anil       // parent
the value of b = 2244 // parent
manish.yadav@ws40-man-lin:~$ 

Take a look at the man page for fork. Also look at waitpid for proper handling of child processes by parent processes so you don't create zombies.

Edit: In response to your questions in the comments, I'll answer how you can simply run each process consecutively.

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}

Of course, isn't the best code, but it's just to illustrate the point. The big idea here is the waitpid call, which causes the parent process to wait until the child process it just forked to terminate. After the child prcoess completes, the parent continues after the waitpid call, starting another iteration of the for loop and forking another (the next) process. This continues until all child process have executed sequentially and execution finally returns to the parent.