Child Process=fork()

fork() is internally implemented using clone()
Creates a new child process. Compelte |CS|DS|SS|HS| of parent is duplicated to child.
New Process control block is created for child. Code Segment is Duplicated using COW(Copy on Write)

                -------------2. fork() Duplicates----------
                |                                         \/                  
                PARENT                                   CHILD
       Stack   Heap     Data Segment              Stack   Heap     Data Segment
    1. | pPtr | "PARN" | g_a=1, g_b=0 |          | pPtr | "PARN" | g_a=1, g_b=0 | 
         |       /\                             
          --------                               3. Child changes its values
                                                   Stack   Heap     Data Segment
                                                 | pPtr | "CHLD" | g_a=10, g_b=50 |
                                                    |       /\
                                                    -------- 
   
    4. 
     PARENT pPtr=PARN, g_a=1, g_b=0
     CHILD  pPtr=CLD, g_a=10, g_b=0

     //Complete Tree
     # pstree -hp |grep a.out
       |-gnome-terminal-(4730)-+-bash(4737)---su(4886)---bash(4908)---a.out(10005)---a.out(10006)
     Parent PID=10005   Child PID=10006
     
     //PID of parent in child
       pid_t ppid = getppid();
            

#include<unistd.h>  //fork
#include<iostream>
#include<cstring>

//DS
int g_a = 1;    //Initialized
int g_b;        //Uninitialized

int main(){
    string str;                       //Stack

    char *p = new char[7];                //Heap
    strcpy(p, "Parent");

    std::cout << "[Before fork] g_a: " << g_a\
    << ", g_b: " << g_b\
            << ", p: " << p << std::endl;

    int k = fork();

    if (k==0){      //CHILD
        g_a = 10;                        //DS
        strcpy(p,"Child");            //Stack
        std::cout << "\n[CHILD] g_a: " << g_a\
        << ", g_b: " << g_b\
        << ", p: " << p << std::endl;
    }else{
        std::cout << "Parent";
    }

    std::cout << "\n[AFTER fork] g_a: " << g_a\
    << ", g_b: " << g_b\
    << ", p:" << p << std::endl;

    delete p;
    return 0;
}

# ./a.out
[Before fork] g_a: 1, g_b: 0, pPtr: PARN

[PARENT]
[CHILD] g_a: 10, g_b: 0, pPtr: CHLD

[AFTER] g_a: 1, g_b: 0, pPtr: PARN		//Notice Executed Twice, 1 for Parent, 1 for Child
[AFTER] g_a: 10, g_b: 0, pPtr: CHLD
            

clone


int clone(int (*fn)(void *), void *stack, int flags, void arg, .../ pid_t *parent_tid, void *tls, pid_t *child_tid */ );
            
API creates a new child process, in a manner similar to fork(2).
Unlike fork(2), the clone(2) allows the child process to share parts of its execution context with the calling process, such as the memory space, the table of file descriptors, and the table of signal handlers.
You can pass different namespace flags to clone(2) to create new namespaces for the child process.

COW(Copy on Write)

Initially, CS, DS, SS, HS all are shared between parent & child .
If any one of them(either parent or child) modifies the data, New page is created & modified data is copied

#include <unistd.h>

/*Code-1: Parent & child process executing same code
void main(){
    fork();
    printf("Hello");
}
Output
    Hello    //Child
    Hello    //Parent
Why? CS for parent and child are same
*/


/*Code-2: COW*/
int dsVar = 10;    //DS variable
void main(){
        int stackVar=10;        //stack variable
        int *heapVar  = malloc(sizeof(int));
        *heapVar=10;    //Heap variable

        if(fork() == 0){    //Child
                stackVar = *heapVar = dsVar = 20;        //Child CS Changed
                printf("%d %d  %d\n", stackVar, *heapVar, dsVar);   //     20 20 20
        }else{    //Parent
                printf("%d %d  %d\n", stackVar, *heapVar, dsVar);   //     10 10 10
        }
}
Output:
10 10  10
20 20  20
            

Code Examples

1 child of parent


#include<unistd.h>

int main(){
    int ret;
    ret = fork();
    if (ret == 0){                       //Child
        printf ("Inside Child\n");
        printf ("[Child] Parent's PID=%d\n", getppid());      //175. Parent's PID is always smaller since its created earlier.
        printf ("[Child] Self PID=%d\n", getpid());           //176
    } else {                            //Parent
        printf ("Inside Parent\n");
        printf ("[Parent] Parent's PID=%d\n", getppid());     //92
        printf ("[Parent] Self PID=%d\n", getpid());          //175
    }
}
$ ./a.out
Inside Parent
Inside Child
[Parent] Parent's PID=92
[Child] Parent's PID=175
[Parent] Self PID=175
[Child] Self PID=176
            

n forks

if we call fork() n number of times. Common code is executed 2n times.

#include<unistd.h>  //fork
int main(){
    fork();
    fork();
    fork();
    
    cout <lt; "Out\n";    //called 8 times
}

# ./a.out
Out
Out
Out
Out
Out
Out
Out
Out
                            fork()
                           /       \
                ---------fork()   fork()-----------
                |         fork()   fork()          |
               / \        / \        /\            /\
            

2 Children of a parent

To create 2 children we need to call fork inside parent.

#include <unistd.h>

void error(char* cString) {
    perror(cString);
    printf("%d", errno);
    exit(0);
}

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <string>
#include <iostream>
extern int errno;

void error(std::string cString) {
    //perror(cString);
    printf("%d", errno);
    exit(0);
}

int main() {
    pid_t child_a, child_b;

    child_a = fork();

    if (child_a == 0) {
        /* Child A code */
        sleep(1);
        std::cout << "Child1:" << getpid() << "\n";
    } else {
        child_b = fork();
        std::cout << "Parent:" << getpid() << "\n";

        if (child_b == 0) {
            /* Child B code */
            std::cout << "Child2:"<< getpid() << "\n";
        } else {
            /* Parent Code */
            std::cout << "Parent:" << getpid() << "\n";
        }
    }
}

$ a.out
Child1: 1234
Parent: 780
Child2: 1235
Parent: 780