18

I'm starting to learn some C and while studying the fork, wait functions I got to a unexpected output. At least for me.

Is there any way to create only 2 child processes from the parent?

Here my code:

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

int main ()
{
    /* Create the pipe */
    int fd [2];
    pipe(fd);

    pid_t pid;
    pid_t pidb;


    pid = fork ();
    pidb = fork ();

    if (pid < 0)
    {
        printf ("Fork Failed\n");
        return -1;
    }
    else if (pid == 0)
    {
        //printf("I'm the child\n");
    }
    else 
    {
        //printf("I'm the parent\n");
    }

    printf("I'm pid %d\n",getpid());

    return 0;
}

And Here is my output:

I'm pid 6763
I'm pid 6765
I'm pid 6764
I'm pid 6766

Please, ignore the pipe part, I haven't gotten that far yet. I'm just trying to create only 2 child processes so I expect 3 "I'm pid ..." outputs only 1 for the parent which I will make wait and 2 child processes that will communicate through a pipe.

Let me know if you see where my error is.

mimoralea
  • 9,590
  • 7
  • 58
  • 59
  • 1
    `fork (2)` is both very simple and one of the most misunderstood calls in the unix API. Just look at the "Related" sidebar. Is there a particular reason you want communication between two children and not between the parent and the child? – dmckee --- ex-moderator kitten Jun 06 '12 at 14:06
  • For the fork() call why are you checking for pid == 0? How do I know which one is the parent and which is the child? – TwilightSparkleTheGeek Jun 27 '14 at 08:59
  • 1
    @TwilightSparkleTheGeek `man fork` states: RETURN VALUE On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately. – mimoralea Nov 06 '14 at 16:49
  • the posted code is calling the second `fork()` from both the parent and the child, After that (assuming neither call to `fork()` fails) there will be 4 processes. I.E. parent, child1 from first call to fork() then parent, child1, child2, child1a from second call to fork() – user3629249 Apr 06 '16 at 21:29

5 Answers5

32
pid = fork (); #1
pidb = fork (); #2

Let us assume the parent process id is 100, the first fork creates another process 101. Now both 100 & 101 continue execution after #1, so they execute second fork. pid 100 reaches #2 creating another process 102. pid 101 reaches #2 creating another process 103. So we end up with 4 processes.

What you should do is something like this.

if(fork()) # parent
    if(fork()) #parent
    else # child2
else #child1
tuxuday
  • 2,977
  • 17
  • 18
  • 5
    That definately works. However, I would recommend using a switch statement instead. The fork function could return a -1 and we can handle this error with case -1 inside a switch statement. – sj755 Jun 06 '12 at 06:41
  • I thought the parent was after the else statement. Why is the parent in the if statement? I'm confused. – TwilightSparkleTheGeek Jun 27 '14 at 08:56
  • 1
    Because fork returns 0 on the child, not the parent. On the parent it returns the PID of the child process you just created, which is more useful. – mimoralea Nov 06 '14 at 16:51
  • @tuxuday can you give a running example? I can't figure out how to write the code for this – Mohsin Sep 09 '16 at 14:52
13

After you create process , you should check the return value. if you don't , the seconde fork() will be executed by both the parent process and the child process, so you have four processes.

if you want to create 2 child processes , just :

if (pid = fork()) {
    if (pid = fork()) {
        ;
    } 
} 

You can create n child processes like this:

for (i = 0; i < n; ++i) {
    pid = fork();
    if (pid > 0) {   /* I am the parent, create more children */
        continue;
    } else if (pid == 0) { /* I am a child, get to work */
        break;
    } else {
        printf("fork error\n");
        exit(1);
    }
}
Confused
  • 1
  • 3
Fei Xue
  • 1,995
  • 5
  • 19
  • 29
3

When a fork statement is executed by the parent, a child process is created as you'd expect. You could say that the child process also executes the fork statement but returns a 0, the parent, however, returns the pid. All code after the fork statement is executed by both, the parent and the child.

In your case what was happening was that the first fork statement created a child process. So presently there's one parent, P1, and one child, C1.

Now both P1 and C1 encounter the second fork statement. The parent creates another child (c2) as you'd expect, but even the child, c1 creates a child process (c3). So in effect you have P1, C1, C2 and C3, which is why you got 4 print statement outputs.

A good way to think about this is using trees, with each node representing a process, and the root node is the topmost parent.

rounak
  • 9,217
  • 3
  • 42
  • 59
0

you can check the value as if ( pid < 0 ) process creation unsuccessful this tells if the child process creation was unsuccessful.. fork returns the process id of the child process if getpid() is used from parent process..

nilesh
  • 1
0

You can create a child process within a child process. This way you can have 2 copies of the original parent process.

int main (void) {
    pid_t pid, pid2;
    int status;

    pid = fork();

    if (pid == 0) { //child process
        pid2 = fork();
        int status2;

        if (pid2 == 0) { //child of child process
            printf("friends!\n");
        }
        else {
            printf("my ");
            fflush(stdout);
            wait(&status2);
        }
    }
    else { //parent process
        printf("Hello ");
        fflush(stdout);
        wait(&status);
    }

    return 0;
}

This prints the following:

Hello my friends!