Open In App

fork() and memory shared b/w processes created using it

Prerequisite: fork() in C

So when we do a fork() what are the sections the two process actually share? Is the heap memory per process? Are the global variables shared? Will malloc return the same address to both? Let us run the program below and take a look at the output of it to clear the questions above. 




// C program to demonstrate working of fork()
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
 
int globalVar = 0; // A global variable
 
int main(void)
{
    // local variable
    int localVar = 0;
 
    int* privateMem = (int*)mmap(
        NULL, sizeof(int), PROT_READ | PROT_WRITE,
        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    int* sharedMem = (int*)mmap(
        NULL, sizeof(int), PROT_READ | PROT_WRITE,
        MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    pid_t childPID = fork();
 
    // Putting value at allocated address
    *privateMem = 0;
    *sharedMem = 0;
 
    if (childPID < 0) // fork was unsuccessful
    {
        printf("\n Fork failed, quitting!!!!!!\n");
        return 1;
    }
 
    if (childPID == 0) // child process
    {
        printf("\n Child Process Initial Value :: localVar"
               " = %d, globalVar = %d",
               localVar, globalVar);
 
        printf("\n Address of malloced privateMem in child "
               "= %p "
               "and value is %d",
               privateMem, *privateMem);
        printf("\n Address of malloced sharedMem in child "
               "= %p "
               "and value is %d",
               sharedMem, *sharedMem);
 
        localVar = 1;
        globalVar = 2;
 
        printf("\n Updated child Process :: localVar = %d, "
               "globalVar = %d",
               localVar, globalVar);
 
        printf("\n lets change the value of privateMem "
               "variable "
               "created by malloc in child");
        *privateMem = 50;
        printf("\n Address of malloced privateMem in child "
               "= %p "
               "and value is %d",
               privateMem, *privateMem);
 
        printf("\n lets change the value of sharedMem "
               "variable "
               "created my malloc in child");
        *sharedMem = 100;
        printf("\n Address of malloced sharedMem in child "
               "= %p "
               "and value is %d\n\n",
               sharedMem, *sharedMem);
 
        exit(EXIT_SUCCESS);
    }
    else {
        wait(NULL); // Wait for child process to exit
 
        printf("\n Parent Process Initial Value :: "
               "localVar = %d, globalVar = %d",
               localVar, globalVar);
 
        printf("\n Address of malloced privateMem in "
               "parent = %p "
               "and value is %d",
               privateMem, *privateMem);
        printf("\n Address of malloced sharedMem in parent "
               "= %p "
               "and value is %d",
               sharedMem, *sharedMem);
 
        localVar = 10;
        globalVar = 20;
        printf("\n Updated parent process :: localVar = %d,"
               " globalVar = %d",
               localVar, globalVar);
 
        printf("\n lets change the value of privateMem "
               "variable "
               "created by malloc in parent");
        *privateMem = 100;
        printf("\n Address of malloced privateMem in "
               "parent= %p "
               "and value is %d",
               privateMem, *privateMem);
 
        printf("\n lets change the value of sharedMem "
               "variable "
               "created my malloc in parent");
        *sharedMem = 400;
        printf("\n Address of malloced sharedMem in parent "
               "= %p"
               " and value is %d \n",
               sharedMem, *sharedMem);
    }
 
    return 0;
}

Output

 Child Process Initial Value :: localVar = 0, globalVar = 0
 Address of malloced privateMem in child = 0x7f245277d000 and value is 0
 Address of malloced sharedMem in child = 0x7f2452750000 and value is 0
 Updated child Process :: localVar = 1, globalVar = 2
 lets change the value of privateMem variable created by malloc in child
 Address of malloced privateMem in child = 0x7f245277d000 and value is 50
 lets change the value of sharedMem variable created my malloc in child
 Address of malloced sharedMem in child = 0x7f2452750000 and value is 100


 Parent Process Initial Value :: localVar = 0, globalVar = 0
 Address of malloced privateMem in parent = 0x7f245277d000 and value is 0
 Address of malloced sharedMem in parent = 0x7f2452750000 and value is 100
 Updated parent process :: localVar = 10, globalVar = 20
 lets change the value of privateMem variable created by malloc in parent
 Address of malloced privateMem in parent= 0x7f245277d000 and value is 100
 lets change the value of sharedMem variable created my malloc in parent
 Address of malloced sharedMem in parent = 0x7f2452750000 and value is 400

Explanation

  1. Both child and parent processes have their own copy of globalVar and localVar. Note that the initial values for the child and parents processes are 0 even after each variable is updated.
  2. Though the address of the privateMem variable returned by malloc is the same in both processes, they are mapped to different physical memory addresses. Otherwise, when the child assigned value of 50 to the memory address 0x7f245277d000, the same 50 would have been shown in the parent. Instead, 0 is shown.
  3. To share memory between processes, the MAP_SHARED flag on mmap must be set. This will guarantee that the parent process can access the changed value made by the child process. Note: To avoid race conditions, the program needs to be synchronized. This can be achieved using wait(NULL). This call will block the parent process until the child process has exited.

Article Tags :