Search code examples
clinuxprocessforkpid

What is fork() doing here?


So I am trying to figure out what this code is doing:

int k = 5;
 if(fork() == fork()) ++k; else --k;
 printf("%d\n", k);

The thing that bothers me is that I receive different outputs:

4
4
4
6
4
4
4
4
4
6
4
4
4
6
4
6
4
4

I have added a PID detector so I see the ids of all the processes:

int main ()
{
   int k = 5;
    if(fork() == fork()) ++k; else --k;
    printf("%d\n", k);
    int pid;
    pid = fork();
    if(pid == 0)
    {
         printf("\n Process id : %d",getpid());
         printf("\n Parrent process id : %d\n" ,getppid());
    }

    return 0;
}

But sometimes I get the output:

Process id : 9472
 Parrent process id : 1413

 Process id : 9474
 Parrent process id : 1413

 Process id : 9471
 Parrent process id : 1413

 Process id : 9473
 Parrent process id : 1413

or:

 Process id : 9557
 Parrent process id : 1413

 Process id : 9556
 Parrent process id : 1413

 Process id : 9558
 Parrent process id : 9554

 Process id : 9559
 Parrent process id : 9553

Please make me understand what is happening here.


Solution

  • I expanded your original code to wait for the children so that you'll be sure to get all output and added some more output.

    You have two forks so there will be four processes in total.

    Only in one of these processes will fork() == fork() be true. It's when the first called of those two fork()s returns to a child process and the next fork() is called and also returns to a child process.

    #include <stdio.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    const char *foo(pid_t a, pid_t b) {
        if (a == b) return "child,child";
        if (a && b) return "parent,parent";
        if (a) return "parent,child";
        return "child,parent";
    }
    
    int main() {
        int k = 5;
        pid_t p1, p2;
    
        if ((p1 = fork()) == (p2 = fork())) {
            ++k;
        } else {
            --k;
        }
    
        printf("%d %s\tppid=%d  pid=%d\n", k, foo(p1, p2), getppid(), getpid());
    
        int wstatus;
        if (p1) wait(&wstatus);
        if (p2) wait(&wstatus);
    }
    

    Example output. Note that the order may change since all the processes run at the same time.

    6 child,child   ppid=2  pid=4
    4 parent,child  ppid=1  pid=3
    4 child,parent  ppid=1  pid=2
    4 parent,parent ppid=0  pid=1
    

    Here the first process, 1, creates 2 and 3 and it is in the case where 2 was created that we got fork() == fork().

        1
       / \
      2   3
     /
    4