22

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

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
Plisken
  • 423
  • 1
  • 4
  • 20
  • 2
    a fork() creates a new process, that gets a copy of the parent data, as it was before the fork(). Also, a call to fork() can have three results, not just 2 or 1 (as the code is doing) the three results are: <0 means error, =0 means child, >0 means parent. The code should always check for all three results. I.E. this: `pid2=fork(); /* B */ pid3=fork(); /* C */` is bad coding practice as it is unknown which process created 'C' (actually there will be 2 of the 'C' processes) Similar considerations exist for process 'E' – user3629249 Sep 27 '15 at 18:17
  • children 'B' and 'C' never reach the printf() statements due to the earlier 'if' statement. Only 'A', 'D', and 'E' ever reach the printf() statements. – user3629249 Sep 27 '15 at 18:30
  • youtube.com/watch?v=WcsZvdlLkPw in this the parent process has a value overwritten by the childs process id is this correct? – Plisken Sep 27 '15 at 18:36

4 Answers4

26

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

Philip Kirkbride
  • 21,381
  • 38
  • 125
  • 225
Rahul Jha
  • 1,131
  • 1
  • 10
  • 25
  • Fork is a system call.As soon as you call it.Your process is duplicated.In child process the pid is set to zero and in the parent process the pid is given a positive value.Now the remaining portion of the code is the same for both the processes(we are executing the same code).So, to distinguish between the processes we use the pid value,which as told earlier is seperate for child & parent – Rahul Jha Sep 27 '15 at 18:30
  • youtube.com/watch?v=WcsZvdlLkPw in this the parent process has value overwritten by the childs process id is this correct? – Plisken Sep 27 '15 at 18:38
  • Please tell me the time where the video confuses you! i cant run through a 7 minute video tutorial of something i know – Rahul Jha Sep 27 '15 at 18:43
  • https://www.youtube.com/watch?feature=player_detailpage&v=WcsZvdlLkPw#t=103 After doing 2 forks he does a third fork because he changed a value in the second fork. – Plisken Sep 27 '15 at 18:46
6
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.

mksteve
  • 12,614
  • 3
  • 28
  • 50
  • so what you're saying is that the child gets the values of the parent but passes back an arbitrary value to the parent such as "1" and that changes the parents value? – Plisken Sep 27 '15 at 18:15
  • @plisken, the value is the process id for the child returned. In the operating system, it creates a new copy of the memory for the process - all the file handles, libraries and allocated memory, are exactly the same. The OS then sets the return value of the fork function to the new pid, for the parent and the child gets a return value of 0. The fork function is a primitive. It can't be written in C/C++ unless you are the operating system. Coming up with pseudo code would not really make sense. – mksteve Sep 27 '15 at 18:22
  • youtube.com/watch?v=WcsZvdlLkPw in this the parent process has value overwritten by the childs process id is this correct? – Plisken Sep 27 '15 at 18:34
  • @Plisken the "overwrite" is the return value. It is describing the change when `x = function(); /* change the value of x */` Not modifying any internal state of the parent *except the return value output from fork* – mksteve Sep 27 '15 at 18:43
  • I understand now thank you. Last query https://www.youtube.com/watch?feature=player_detailpage&v=WcsZvdlLkPw#t=103 can you tell me why he forks a third time? He did 2 and after the second fork he had to fork from the first one again. why is this? – Plisken Sep 27 '15 at 18:47
  • @Plisken, the processes are all independent, they all have to execute the whole program, which means. – mksteve Sep 27 '15 at 18:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/90746/discussion-between-mksteve-and-plisken). – mksteve Sep 27 '15 at 19:04
3

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;
}
leakim
  • 41
  • 4
  • I understand that, i do. But watch this https://www.youtube.com/watch?v=WcsZvdlLkPw The fork passes a value up to the parent, presumably the new process id. Is this correct? – Plisken Sep 27 '15 at 18:22
  • Yes this is true, fork() will tell the parent what pid the new child has and I stated this. Please also see the documentation in the link provided under the section "RETURN VALUE" – leakim Sep 27 '15 at 18:41
  • I have read it I appreciate it very much it's extremely helpful. But this is my last query. Once the parents value is changed with the childs process id why is it necessary to alter other processes as is done in the video. – Plisken Sep 27 '15 at 18:44
1

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