[c] Fork() function in C

Below is an example of the Fork function in action. Below is also the output. My main question has to to do with the a fork is called how values are changed. So pid1,2 and 3 start off at 0 and get changed as the forks happen. Is this because each time a fork happens the values are copied to the child and the specific value gets changed in the parent? Basically how do values change with fork functions?

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

int main() {
    pid_t pid1, pid2, pid3;
    pid1=0, pid2=0, pid3=0;
    pid1= fork(); /* A */
    if(pid1==0){
        pid2=fork(); /* B */
        pid3=fork(); /* C */
    } else {
        pid3=fork(); /* D */
        if(pid3==0) {
            pid2=fork(); /* E */
        }
        if((pid1 == 0)&&(pid2 == 0))
            printf("Level 1\n");
        if(pid1 !=0)
            printf("Level 2\n");
        if(pid2 !=0)
           printf("Level 3\n");
        if(pid3 !=0)
           printf("Level 4\n");
       return 0;
    }
}

Then this is the execution.

----A----D--------- (pid1!=0, pid2==0(as initialized), pid3!=0, print "Level 2" and "Level 4")
    |    |
    |    +----E---- (pid1!=0, pid2!=0, pid3==0, print "Level 2" and "Level 3")
    |         |
    |         +---- (pid1!=0, pid2==0, pid3==0, print "Level 2")
    |
    +----B----C---- (pid1==0, pid2!=0, pid3!=0, print nothing)
         |    |
         |    +---- (pid1==0, pid2==0, pid3==0, print nothing)
         |
         +----C---- (pid1==0, pid2==0, pid3!=0, print nothing)
              |
              +---- (pid1==0, pid2==0, pid3==0, print nothing)

Ideally below is how I would like to see it explained as this way makes sense to me. The * are where my main confusion lies. When the child forks for example pid1 = fork(); that creates a process with all the values of the parent, but does it then pass up a value like lets say 1 to the parents pid1? Meaning the child would have pid 1=0, pid2=0 and pid3=0 and the parent then as pid1=2 and pid2 and 3 equal to 0? enter image description here

This question is related to c linux process operating-system

The answer is


int a = fork(); 

Creates a duplicate process "clone?", which shares the execution stack. The difference between the parent and the child is the return value of the function.

The child getting 0 returned, and the parent getting the new pid.

Each time the addresses and the values of the stack variables are copied. The execution continues at the point it already got to in the code.

At each fork, only one value is modified - the return value from fork.


System call fork() is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Therefore, we have to distinguish the parent from the child. This can be done by testing the returned value of fork()

Fork is a system call and you shouldnt think of it as a normal C function. When a fork() occurs you effectively create two new processes with their own address space.Variable that are initialized before the fork() call store the same values in both the address space. However values modified within the address space of either of the process remain unaffected in other process one of which is parent and the other is child. So if,

pid=fork();

If in the subsequent blocks of code you check the value of pid.Both processes run for the entire length of your code. So how do we distinguish them. Again Fork is a system call and here is difference.Inside the newly created child process pid will store 0 while in the parent process it would store a positive value.A negative value inside pid indicates a fork error.

When we test the value of pid to find whether it is equal to zero or greater than it we are effectively finding out whether we are in the child process or the parent process.

Read more about Fork


I think every process you make start executing the line you create so something like this...

pid=fork() at line 6. fork function returns 2 values 
you have 2 pids, first pid=0 for child and pid>0 for parent 
so you can use if to separate

.

/*
    sleep(int time) to see clearly
    <0 fail 
    =0 child
    >0 parent
*/
int main(int argc, char** argv) {
    pid_t childpid1, childpid2;
    printf("pid = process identification\n");
    printf("ppid = parent process identification\n");
    childpid1 = fork();
    if (childpid1 == -1) {
        printf("Fork error !\n");
    }
    if (childpid1 == 0) {
        sleep(1);
        printf("child[1] --> pid = %d and  ppid = %d\n",
                getpid(), getppid());
    } else {
        childpid2 = fork();
        if (childpid2 == 0) {
            sleep(2);
            printf("child[2] --> pid = %d and ppid = %d\n",
                    getpid(), getppid());
        } else {
            sleep(3);
            printf("parent --> pid = %d\n", getpid());
        }
    }
    return 0;
}

//pid = process identification
//ppid = parent process identification
//child[1] --> pid = 2399 and  ppid = 2398
//child[2] --> pid = 2400 and ppid = 2398
//parent --> pid = 2398

linux.die.net

some uni stuff


First a link to some documentation of fork()

http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

The pid is provided by the kernel. Every time the kernel create a new process it will increase the internal pid counter and assign the new process this new unique pid and also make sure there are no duplicates. Once the pid reaches some high number it will wrap and start over again.

So you never know what pid you will get from fork(), only that the parent will keep it's unique pid and that fork will make sure that the child process will have a new unique pid. This is stated in the documentation provided above.

If you continue reading the documentation you will see that fork() return 0 for the child process and the new unique pid of the child will be returned to the parent. If the child want to know it's own new pid you will have to query for it using getpid().

pid_t pid = fork()
if(pid == 0) {
    printf("this is a child: my new unique pid is %d\n", getpid());
} else {
    printf("this is the parent: my pid is %d and I have a child with pid %d \n", getpid(), pid);
}

and below is some inline comments on your code

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

int main() {
    pid_t pid1, pid2, pid3;
    pid1=0, pid2=0, pid3=0;
    pid1= fork(); /* A */
    if(pid1 == 0){
        /* This is child A */
        pid2=fork(); /* B */
        pid3=fork(); /* C */
    } else {
        /* This is parent A */
        /* Child B and C will never reach this code */
        pid3=fork(); /* D */
        if(pid3==0) {
            /* This is child D fork'ed from parent A */
            pid2=fork(); /* E */
        }
        if((pid1 == 0)&&(pid2 == 0)) {
            /* pid1 will never be 0 here so this is dead code */
            printf("Level 1\n");
        }
        if(pid1 !=0) {
            /* This is always true for both parent and child E */
            printf("Level 2\n");
        }
        if(pid2 !=0) {
           /* This is parent E (same as parent A) */
           printf("Level 3\n");
        }
        if(pid3 !=0) {
           /* This is parent D (same as parent A) */
           printf("Level 4\n");
        }
    }
    return 0;
}

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to process

Fork() function in C How to kill a nodejs process in Linux? Xcode process launch failed: Security Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes Linux Script to check if process is running and act on the result CreateProcess error=2, The system cannot find the file specified How to make parent wait for all child processes to finish? How to use [DllImport("")] in C#? Visual Studio "Could not copy" .... during build How to terminate process from Python using pid?

Examples related to operating-system

Context.startForegroundService() did not then call Service.startForeground() Fork() function in C python: get directory two levels up Find Process Name by its Process ID Best way to find os name and version in Unix/Linux platform How to run a program without an operating system? How to make parent wait for all child processes to finish? Get operating system info Running windows shell commands with python What are the differences between virtual memory and physical memory?