RhoThanos
RhoThanos

Reputation: 1

if(fork()) and if(!fork()) - how do they work?

Let's say we have the following:

pid_t pid;
pid = fork();
if(pid == 0) {
        if(fork()) printf("A");
        else printf("B");
        printf("C");
}
else {
        if(!fork()) printf("A");
        else if (fork()) printf("B");
        else printf("C");
}
    

How many A's, B's and C's are going to be printed?

I'm a little bit confused with how fork() works inside "if" and whether I'm in parent or child process.

Upvotes: -2

Views: 311

Answers (3)

Bruno
Bruno

Reputation: 621

First, the mandatory reminder: The fork() system call returns:

  • Child process: 0
  • Parent process: PID of child process

Below is your code, indented, and with comments about process per line :

#include <stdio.h>
#include <unistd.h>

int main()
{
    pid_t pid;

    /* P1 = parent */
    pid = fork();                                 /* P1 creates P2 */
    if(pid == 0) {                                /* P2 */
        if(fork())                                /* P2 creates P3, P2 branch  */
            printf("A");                          /* P2 */
        else                                      /* P3 */
            printf("B");                          /* P3 */
        printf("C");                              /* P2 and P3 */
    } else {                                      /* P1 */
        if(!fork())                               /* P1 creates P4, P4 branch */
            printf("A");                          /* P4 */
        else                                      /* P1 */
            if (fork())                           /* P1 creates P5, P1 branch */
                printf("B");                      /* P1 */
            else                                  /* P5 */
                printf("C");                      /* P5 */
    }
                                                  /* P1, P2, P3, P4, P5 */
}

The process tree with their output is:

                      P1 (B)
                      |
         ---------------------------
         |            |            |
         P2 (A + C)   P4 (A)       P5 (C)
         |
         P3 (B + C)

Note that for each process, the order of output is as written above (for example, P2 will print A then C). But output between processes is unknown, they could be in any order (for example A(P2) then B(P1) then C(P5) then C(P2), etc...).

About processes, we know that P1 creates P2, P4, P5 in this order, but P3, created by P2, can effectively be created before P4, between P4 and P5, or after P5.

Upvotes: 0

Nassim Ouali
Nassim Ouali

Reputation: 1

The outputs may differ depending on the way the processes are executed by your machine but the concept is that when you use if(fork()){//block} you're basically creating a new child process and only allowing the parent process to access the block of code inside the if statement since for the child process the fork() returns 0 which is false and for the parent it returns the child PID which is != 0 meaning it's 'true', similarly the if(!fork()){//block} does the opposite and only allows the child process to enter the block of code. The output will consist of a combination of A, B, and C printed by different processes. The exact order depends on the scheduling of the processes.

Upvotes: 0

John Bollinger
John Bollinger

Reputation: 181199

I'm a little bit confused with how fork() works inside "if" and whether I'm in parent or child process.

fork() works the same way inside an if condition as it does anywhere else. It causes a duplicate of the current process to be created, and returns in both processes. In the child, the return value is 0, which is falsey, whereas in the parent (on success) it returns the child's pid, which is non-zero and therefore truthy.

Thus with ...

if(fork()) printf("A");
        else printf("B");

... for example, the printf("A") branch is taken in the parent, where fork() returned a truthy value, and the else printf("B") branch is taken in the child (supposing that the fork succeeds) where fork() returned 0.

It is not necessary to store the return value of fork(), or any other function in a variable. It can be used directly, which is not particularly uncommon, or it can even be ignored altogether, which also is not uncommon.

I leave it to you to work out the actual solution to the exercise.

Upvotes: 2

Related Questions