0

I'm trying to use the multiple fork() calls to create several children with different task I found a code on Multiple child process

Which is really close for what I want , yet I couldn't fully understand it

pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild != 0)
{
  // In parent
  secondChild = fork();
  if(secondChild != 0)
  {
    // In parent
  }
  else
  {
    // In secondChild
  }
}
else
{
  // In firstChild
}

My questions are:

  • How many process have been created (I assume that we have 4 since it's 2 forks!)?
  • In this part of the code

firstChild = fork();
if(firstChild != 0)
{
    // In parent
    secondChild = fork();
    if(secondChild != 0)
    {
        // In parent
    }

Does "//in parent" mean both of them are the same process (they have the same PID when I tried to test it).

  • How can I create 3 children using 2 forks?( I can draw the tree that ends with 4 leaves 3 of them are children and 1 parent)

Thank you (please feel free to tell me if I'm not totally getting the Fork concept)

Community
  • 1
  • 1
Muhannad
  • 467
  • 4
  • 28

2 Answers2

1

How many process have been created (I assume that we have 4 since it's 2 forks!)?

Depending on the result of your forks it should be 0 to 2. Probably 2 if nothing goes wrong. There's a parent process that forks 2 children processes.

Does "//in parent" mean both of them are the same process (they have the same PID when I tried to test it).

Yes. In your case the code is checking for a return value of fork being non zero. That's not a very good idea since it covers 2 distinct cases:

  • It could be less than zero indicating an error, or ...
  • It could be greater than zero indicating to the parent the pid of the newly spawned process Anyway ... considering all goes well and both the forks succeed, you will end up with a parent process having 2 different children.

How can I create 3 children using 2 forks?( I can draw the tree that ends with 4 leaves 3 of them are children and 1 parent

Something like this should do the trick:

firstChild = fork();
if (firstChild < 0) {
    exit(EXIT_FAILURE);
    perror("fork");
}
secondChild = fork();

Notice that by not checking the return value of fork() any more I'm getting a child process continuing execution at the same place as the parent. So the next fork will actually be executed by both the parent and the children each spawning a new process. So I'll get something like this ...

parent─┬─child1───(child1's child)
       └─child2

I can't think of any way you can get this with only 2 forks though:

parent─┬─child1
       ├─child3
       └─child2

Note: It's customary on stackoverflow to only limit yourself to one question per topic.

dragosht
  • 3,237
  • 2
  • 23
  • 32
  • thank you very much man and I'm sorry for any inconvenience, one more question ,since child 1 is a parent and a child at the same, when I use (firstChild!=0) an I in the parent or child1 process? – Muhannad Feb 27 '15 at 07:04
  • @user3382285 I'm not sure I understand your question above - could you please rephrase that?... That `firstChild!=0` check would help you make the distinction between your parent/child1 code (>0 --> parent, ==0 --> child1). – dragosht Feb 27 '15 at 07:47
  • when I use a code that has Fork() fork() like yours firstChild = fork(); if (firstChild < 0) { exit(EXIT_FAILURE); perror("fork"); } secondChild = fork(), this will create 4 processes right? can I make each process prints something else for eample (I'm process#1 and my PID is%d ", getpid());? – Muhannad Mar 01 '15 at 00:06
  • There will be a total of 4 processes (but only three of them created by fork - see the pstree-like output above). And sure ... just go ahead and add those `printfs` after the `fork`s if you want to see their PIDs. – dragosht Mar 01 '15 at 07:22
  • but I couldn't figure it out how can I make them do different things (the printf worked because I used getpid() .what if I wanted them to do different functions.Like the code in the question gives you the space for each children to include your own code/ function and the child only will execute it. – Muhannad Mar 04 '15 at 09:18
  • Well ... then you would have to check that return value of fork to determine which process you're in. And based on that you can make those processes do whatever you want them to do. – dragosht Mar 04 '15 at 11:21
0

The following code shows how to create 4 process (1 parent 3 children) with only 2 forks

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

int *list;

void calculate_average(int );
void calculate_maximum(int);
void calculate_minimum(int);

void calculate_average(int count) 
{
        int i, total = 0;


        for (i = 0; i < count; i++)
                total += list[i];

        double average = total / count;
        
 printf("average is %f\n",average);

}

void calculate_maximum(int count)
{
        int i;

        int maximum = list[0];

        for (i = 1; i < count; i++)
                if (list[i] > maximum)
                        maximum = list[i];

 printf("maximum is %d\n",maximum);
}

void calculate_minimum(int count)
{
        int i;

        int minimum = list[0];

        for (i = 1; i < count; i++)
                if (list[i] < minimum)
                        minimum = list[i];
 printf("minimum is %d\n",minimum);
}

int main(int argc, char *argv[])
{
 pid_t pid, pid1;

 int num_of_args = argc-1;
 int i;

 /* allocate memory to hold array of integers */
        list = malloc(sizeof(int)*num_of_args);

        for (i = 0; i < num_of_args; i++)
                list[i] = atoi(argv[i+1]);
        
 printf("The %d number of input ingeters are\n",num_of_args);
        for (i = 0; i < num_of_args; i++)
                printf("%d\n",list[i]);

 /* fork a child process */
 pid = fork();

 if (pid < 0) { /* error occurred */
  fprintf(stderr, "Fork Failed\n");
  return 1;
 }
 else if (pid == 0) { /* P2 */
  pid1=getppid();
  calculate_average(num_of_args);
 }

 else {   /* P1 */
  pid1=getpid();
  wait(NULL);
 }
 
  pid = fork();
 
 if (pid < 0) { /* error occurred */
  fprintf(stderr, "Fork Failed\n");
  return 1;
 }
 
 else if (pid == 0) { /* could be either P3 or P4 */
  if (getppid() == pid1) { /* P3 */
   calculate_minimum(num_of_args);
  } 

  else {  /* P4 */
   calculate_maximum(num_of_args);
  }
 }
 
 else { 
  wait(NULL);
 }
    
     return 0;
}

Note that one of the children will be a parent for a grandchild

Muhannad
  • 467
  • 4
  • 28