Click here to Skip to main content
15,896,727 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Here is a code that creates two childern using fork. My question is how can we create mutiple grandchildern and great grandchildern at the same time . And the line 21 of code gives an unexpected output i.e instead on one parent id it gives three id's.


Here is the output :-
This is a child1 process and pid is 3271
This is child2 process and pid is 3272
The parent process has pid 2206
The parent process has pid 3270
The parent process has pid 1.



#include<stdio.h>
main()
{
  int child1,child2;
  int i;
  child1 = fork();
  if(child1==0)
  {
    printf("This is a child1 process and pid is %d\n", getpid());
  }
   else
    {
          child2=fork();     
	  if(child2==0)
	    {
              printf("This is child2  process and pid is %d\n",getpid());
	    }
      }
	sleep(1);
       printf("The parent process has pid %d\n",getppid());

          
}
Posted

1 solution

The child processes inherit/copy a lot of resources, memory, code and handles from the parent process. For this reason the sleep(1) and the printf() that follows it is executed by all branches of your code, both by the parent and the two children. If you want to execute it only by the original parent process after spawning both children then you have to move the sleep along with the printf into an else branch of the inner if:
C++
if(child2==0)
{
   printf("This is child2  process and pid is %d\n",getpid());
} else {
   sleep(1);
   printf("The parent process has pid %d\n",getppid());
}

There it is executed only by the original parent after spawning both children. You can create grandchildren by forking() once in the child process. You can create a great child by forking once in a grand child process... But remember, a lot of resources and all the code is copied by every forked children (like your sleep and printf) and the execution flow goes as the language flow constructs dictate!

Here is a piece of code that spawns the following process hierarchy:
parent
 +--child
     +--grandchild1
     +--grandchild2


This is a good example of how not to write a program. This is a big piece of disgusting spaghetti code where many bugs can hide easily.
C++
#include<stdio.h>

void variation1()
{
    pid_t child, grandchild1, grandchild2;
    int child_status, grandchild1_status, grandchild2_status;
    printf("The parent process has pid %d\n", getpid());
    child = fork();
    if(child == 0)
    {
        // child
        printf("This is a child process and pid is %d\n", getpid());

        grandchild1 = fork();
        if (grandchild1 == 0)
        {
            // grandchild1
            printf("This is grandchild1 and pid is %d\n", getpid());
            sleep(1);
            exit(5);
        }
        else if (grandchild1 > 0)
        {
            // child
            grandchild2 = fork();
            if (grandchild2 == 0)
            {
                // grandchild2
                printf("This is grandchild2 and pid is %d\n", getpid());
                sleep(1);
                exit(6);
            }
            else if (grandchild2 > 0)
            {
                // child
                waitpid(grandchild2, &grandchild2_status, 0);
                if (WIFEXITED(grandchild2_status))
                    printf("grandchild2 has exited with exit code %d\n", WEXITSTATUS(grandchild2_status));
                else
                    printf("grandchild2 has terminated abnormally\n");
            }
            else
            {
                printf("Error forking grandchild2!\n");
            }

            // child
            waitpid(grandchild1, &grandchild1_status, 0);
            if (WIFEXITED(grandchild1_status))
                printf("grandchild1 has exited with exit code %d\n", WEXITSTATUS(grandchild1_status));
            else
                printf("grandchild1 has terminated abnormally\n");
        }
        else
        {
            printf("Error forking grandchild1!\n");
        }
        exit(0);
    }
    else if (child > 0)
    {
        // parent
        waitpid(child, &child_status, 0);
        if (WIFEXITED(child_status))
            printf("child has exited with exit code %d\n", WEXITSTATUS(child_status));
        else
            printf("child has terminated abnormally\n");
    }
    else
    {
        printf("Error forking child!\n");
    }
}


Here is a piece of code that should do nearly the same but it is much cleaner and easier to understand. It is designed in a much better way and its easier to modify/maintain without introducing bugs:

C++
// returns the exitcode of the child process
typedef int (*child_func_pointer_t)();

// returns -1 on error, child pid otherwise
pid_t fork_child_in_function(child_func_pointer_t child_func, const char* child_name)
{
    pid_t child_pid = fork();
    if (child_pid == 0)
    {
        printf("Hello! I'm child %s and I've just started with pid=%d (parent_pid=%d)\n", child_name, getpid(), getppid());
        exit(child_func());
    }
    if (child_pid < 0)
        printf("Error forking %s!\n", child_name);
    return child_pid;
}

void wait_child(pid_t child_pid, const char* child_name)
{
    int child_status;
    waitpid(child_pid, &child_status, 0);
    if (WIFEXITED(child_status))
        printf("%s has exited with exit code %d\n", child_name, WEXITSTATUS(child_status));
    else
        printf("%s has terminated abnormally\n", child_name);
}

void fork_and_wait_child(child_func_pointer_t child_func, const char* child_name)
{
    pid_t child_pid = fork_child_in_function(child_func, child_name);
    if (child_pid > 0)
        wait_child(child_pid, child_name);
}


int grandchild1_func()
{
    sleep(1);
    return 5;
}

int grandchild2_func()
{
    sleep(1);
    return 6;
}

int child_func()
{
    int grandchild1_pid, grandchild2_pid;
    grandchild1_pid = fork_child_in_function(grandchild1_func, "grandchild1");
    grandchild2_pid = fork_child_in_function(grandchild2_func, "grandchild2");
    if (grandchild1_pid > 0)
        wait_child(grandchild1_pid, "grandchild1");
    if (grandchild2_pid > 0)
        wait_child(grandchild2_pid, "grandchild2");
    return 0;
}

void variation2()
{
    fork_and_wait_child(child_func, "child");
}

I haven't tested any of these codepieces but this is a very good "pseudo code" that shows how to do things well and shows the difference between junk code and well designed code.
 
Share this answer
 
v7
Comments
Member 10200096 17-Aug-13 8:52am    
This is the same way how we creating second child (child2) in the given code. Correct me if i am wrong? Basically i am not getting the difference between how to create child and grandchild.
pasztorpisti 17-Aug-13 8:55am    
No. You create a child that executes the first branch of your if and the parent goes to the else branch. So in the else branch you create another child by the very same parent process. If you complete your code with my patch then the parent process goes on into the else branch of the inner if, so only the original parent process will sleep and printf.
Member 10200096 17-Aug-13 9:02am    
ok ohkay :) I got it right . One more thing like if we want to create like some 4 grandchildern how do we distribute it as in child1 creates 2 more processes and child2 too do the same That in total make 4 grandchild of the same process?
pasztorpisti 17-Aug-13 9:10am    
That should be obvious: always go to the right branch of the if and fork there. fork and go to the child branch. In the child branch fork and one branch of this second fork is a grand child and the other branch is the very same child process from which we started teh second fork so if you want to fork another grandchild then you fork again in this branch. What is confusing is that the "hierarchy" of your embedded if blocks/branches is not the same as the hierarchy of processes created by your forks.
If you understand forking you have to be able to do it. fork is inconvenient and mysterious for the first time and you have to make sure that a process doesn't run on code that is there to be executed in another process. The sleep/printf was such mistake.
pasztorpisti 17-Aug-13 10:04am    
Modified my answer with two codesnippets. Eximining them you should be able to create any kind of process hierarchy.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900