The difference between fork and vfork

Both fork() and vfock() create a process, so what's the difference between them? There are three differences in summary:
1. fork (): the child process copies the data segment of the parent process, code segment
    vfork (): the child process shares the data segment with the parent process
2. fork () The execution order of the parent and child processes is uncertain
    vfork guarantee The child process runs first , and the data is shared with the parent process before calling exec
     or exit, and the parent process may be scheduled to run after it calls exec or exit.
3. vfork () ensures that the child process runs first, and the parent process may be scheduled to run after she calls exec or exit. If the
   child process depends on further actions of the parent process before calling these two functions, it will cause a deadlock.
Here are some examples to illustrate:
First: the example of the child process copying the code segment of the parent process:

  1. #include<sys/types.h>  
  2. #include<unistd.h>  
  3. #include<stdio.h>  
  4.   
  5. intmain  ()  
  6. {  
  7.     pid_t pid;  
  8.     pid = fork();  
  9.     if(pid<0)  
  10.         printf("error in fork!\n");  
  11.     elseif(pid == 0)   
  12.         printf("I am the child process,ID is %d\n",getpid());  
  13.     else   
  14.         printf("I am the parent process,ID is %d\n",getpid());  
  15.     return 0;  
  16.   
  17. }  


operation result:

  1. [root@localhost fork]# gcc -o fork fork.c   
  2. [root@localhost fork]# ./fork  
  1. I am the child process,ID is 4711  
  2. I am the parent process,ID is 4710  


Why are both languages ​​printed? This is because the fork() function is used to create a new
process . The new process is called a child process, and the original process is called a parent process. There are two return values ​​of fork(), the child process. Return 0, the
parent process returns the process number of the child process, and the process numbers are all non-zero positive integers, so the value returned by the parent process must be greater than zero,
before the pid=fork(); statement, only the parent process is running, and in pid= After fork();, both the parent process and the newly created child process
are running, so if pid==0, then it must be the child process, if pid! =0 (in fact it must be greater than 0), then the
parent process is running. And we know that the child process of the fork() function copies the code segment of the parent process, so the child process also
has
if(pid<0)
         printf("error in fork!");
     else if(pid==0)
         printf( "I am the child process,ID is %d\n",getpid());
     else
         printf("I am the parent process,ID is %d\n",getpid());
}
Such a piece of code, so the above This code will be executed once by the parent process and the child process, and finally due to the pid= = 0 of the child process,

And print out the first sentence, the pid of the parent process>0, and print out the second sentence. So the above results are obtained.
Let's look at an example of copying the data segment:

  1. #include<sys/types.h>  
  2. #include<unistd.h>  
  3. #include<stdio.h>  
  4.   
  5. intmain  ()  
  6. {  
  7.     pid_t pid;  
  8.     int cnt = 0;  
  9.     pid = fork();  
  10.     if(pid<0)  
  11.         printf("error in fork!\n");  
  12.     elseif(pid == 0)   
  13.     {  
  14.         cnt++;  
  15.         printf("cnt=%d\n",cnt);  
  16.         printf("I am the child process,ID is %d\n",getpid());  
  17.     }  
  18.     else  
  19.     {  
  20.         cnt++;  
  21.         printf("cnt=%d\n",cnt);  
  22.         printf("I am the parent process,ID is %d\n",getpid());  
  23.     }  
  24.     return 0;  
  25. }  

 

What do you think the printed value should be? Is it 2? Let's take a look at the results

  1. [root@localhost fork]# ./fork2  
  2. cnt=1  
  3. I am the child process,ID is 5077  
  4. cnt=1  
  5. I am the parent process,ID is 5076  

 

Why not 2? Because we once emphasized that the fork () function child process copies the data segment code segment of the parent process, so
cnt++;
    printf("cnt= %d\n",cnt);

    return 0
will be executed once by the parent and child processes, but the child process will make its own data segment (this data segment
is exactly the same as the one copied from the parent process) count+1 when the child process executes, and the same parent process executes its own data. The count+1 in the segment,
they do not affect each other, and the result is as above.


Then look at vfork(). If the fork() in the above program is changed to vfork(), what will the running result
look like ?

  1. [root@localhost fork]# gcc -o fork3 fork3.c   
  2. [root@localhost fork]# ./fork3  
  3. cnt=1  
  4. I am the child process,ID is 4711  
  5. cnt=1  
  6. I am the parent process,ID is 4710  
  7. segfault  

 

Originally vfock () is a shared data segment, the result should be 2, why not the expected 2? Let's look at a knowledge point first:
Another difference between vfork and fork is: vfork ensures that the child process runs first, and the parent process may be scheduled to run
after . If the child process depends on further action from
the , a deadlock will result.
In this way, after fork() in the above program is changed to vfork(), vfork() creates child process without calling exec or exit,
so it will eventually lead to deadlock.
How to change it? See the program below:

  1. #include<sys/types.h>  
  2. #include<unistd.h>  
  3. #include<stdio.h>  
  4.   
  5. intmain  ()  
  6. {  
  7.     pid_t pid;  
  8.     int cnt = 0;  
  9.     pid = vfork();  
  10.     if(pid<0)  
  11.         printf("error in fork!\n");  
  12.     elseif(pid == 0)   
  13.     {  
  14.         cnt++;  
  15.         printf("cnt=%d\n",cnt);  
  16.         printf("I am the child process,ID is %d\n",getpid());  
  17.        _exit(0);  
  18.     }  
  19.     else  
  20.     {  
  21.         cnt++;  
  22.         printf("cnt=%d\n",cnt);  
  23.         printf("I am the parent process,ID is %d\n",getpid());  
  24.     }  
  25.     return 0;  
  26.   
  27. }  


 

If there is no _exit (0), the child process does not call exec or exit, so the parent process is impossible to execute, and the parent process may be scheduled to run after the child
process calls exec or exit.
So we add _exit(0); to make the child process exit and the parent process to execute, so the statement after else will be executed by the parent process, and
because the data is shared with the parent process before the child process calls exec or exit, so After the child process exits, the
data changed to 1. After the child process exits, the parent process executes again, and finally the count becomes 2. See the actual
running result:

  1. [root@localhost fork]# gcc -o fork3 fork3.c   
  2. [root@localhost fork]# ./fork3  
  3. cnt=1  
  4. I am the child process,ID is 4711  
  5. cnt=2  
  6. I am the parent process,ID is 4710  

 

A paragraph copied from the Internet can be understood again:
why there is vfork, because the previous fork was stupid, when it creates a child process, it will create a new address
space , and copy the resources of the parent process, but often in the child process The exec call will be executed in the middle, so the previous copy
work is wasted effort, in this case, smart people come up with vfork, the child process it generates will temporarily
share the address space with the parent process (actually, the thread Because the child process is
running , so the child process cannot perform write operations, and when the son occupies the house of Laozi, he should aggrieved Laozi
and let him rest outside. (blocking), once the son executes exec or exit, the son has bought his own
house , and at this time, the family is separated.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326749422&siteId=291194637