Differences between fork and vfork in Linux
The method for creating a new process is only used by an existing process to call fork () or vfork ()
1. fork () function
Returned value: Success: parent process: PID of the child process returned
Sub-process: Return 0
Failed: parent process returns-1
A child process is a copy of the parent process. That is, the child process obtains the copy of the Data Segment and heap and stack segment from the parent process. New memory needs to be allocated (not shared with the parent process, but separately allocated). For read-only code segments, generally, shared memory is used for access.
After fork is returned, both the child process and the parent process start to execute the next statement that calls the fork function.
Because the sub-process has nothing to do with the execution of the parent process, the parent process can run before the sub-process, or the sub-process can run before the parent process
Eg:
Myfork. c
Makefile
Running result
When the previous fork creates a sub-process, it creates a new address space and copies the resources of the parent process. Then there are two actions: 1. execute the code segment copied from the parent process (the process wants to copy itself, so that the parent and child processes can execute code of different segments at the same time); 2. call exec to execute a new code segment (the process wants to execute another program)
When a process calls exec, a process replaces the text, Data, stack, and heap segments of the current process. In this way, the previous copy work is in vain. In this case, people come up with vfork.
Vfork does not copy the process environment of the parent process, and the child process runs in the address space of the parent process. Therefore, the child process cannot perform write operations and the son "occupies" the father's house, I want to grievance my father and let him rest (blocking) outside. Once the son executes exec or exit, it is equivalent to buying his own house. At this time, it is equivalent to dividing the house.
2. vfork () function
The main purpose of vfork to create a new process is to call the exec function to execute another new program. Before exec or exit is called, the sub-process runs to share the data segment with the parent process.
In a vfork call, the child process runs first, and the parent process hangs until the child process calls exec or exit. After that, the execution sequence of the Parent and Child processes is no longer limited.
Eg:
Myvfork. c
Makefile
Running result
A classic example
Test. c
- # Include <stdio. h>
- # Include <stdlib. h>
- # Include <sys/types. h>
- # Include <unistd. h>
- Void test ()
- {
- Pid_t pid;
- Pid = vfork ();
- If (pid <0) // failed
- {
- Printf ("vfork error \ n ");
- Exit (0 );
- }
- Else if (pid = 0)
- {
- Printf ("1: child pid = % d, ppid = % d \ n", getpid (), getppid ());
- Return; // after the return operation is completed, the control is handed over to the calling function. After exit () is executed, the control is handed over to the system and changed to _ exit (0). Another result is returned.
- }
- Else
- {
- Printf ("2: parent pid = % d, ppid = % d \ n", getpid (), getppid ());
- }
- }
- Void fun ()
- {
- Int I = 0;
- Int buf [100];
- For (; I <100; I ++)
- {
- Buf [I] = 0;
- }
- Printf ("3: child pid = % d, ppid = % d \ n", getpid (), getppid ());
- }
- Int main ()
- {
- Test ();
- Fun ();
- Return 0;
- }
# Include <stdio. h> # include <stdlib. h> # include <sys/types. h> # include <unistd. h> void test () {pid_t pid; pid = vfork (); if (pid <0) // failure {printf ("vfork error \ n "); exit (0);} else if (pid = 0) {printf ("1: child pid = % d, ppid = % d \ n", getpid (), getppid (); return; // after the return operation is completed, the control is handed over to the calling function. After exit () is executed, the control is handed over to the system and changed to _ exit (0 ), there will be another result} else {printf ("2: parent pid = % d, ppid = % d \ n", getpid (), getppid ());}} void fun () {int I = 0; int buf [100]; for (; I <100; I ++) {buf [I] = 0 ;} printf ("3: child pid = % d, ppid = % d \ n", getpid (), getppid () ;}int main () {test (); fun (); return 0 ;}
Makefile
Running result
The program encountered an error in subsequent execution, and you can know that it was an error in the parent process.
When the vfork function is called, the sub-process runs before the parent process. When the test () function is called, The stack space of the test function is cleared after the sub-process is executed, then the sub-process calls the fun () function, overwrites the stack space of test, and continues to execute the fun function. However, when the sub-process exits, the parent process is executed. However, when the test function returns, the stack space has been destroyed by the quilt process and does not exist. Therefore, a stack error occurs.
Differences:
1. vfork ensures that the sub-process runs first. After it calls exec or exit, the parent process can be scheduled to run. Then, the execution sequence of the Parent and Child processes is no longer limited. If the child process is dependent on the further action of the parent process before exec or exit is called, a deadlock will occur.
2. fork needs to copy the process environment (Data Segment) of the parent process, while vfork does not need to completely copy the process environment (Data Segment) of the parent process. Before exec or exit is called, the Parent and Child processes share the process environment (Data Segment), which is equivalent to the thread concept. In this case, the parent process is blocked and waited (because the child process runs first ).
Terminate the sub-process:
The exit and _ exit functions are used to terminate a program normally. The _ exit () function immediately enters the kernel. The exit () function must first execute some cleanup operations (including calling and executing each terminate processing program, close all standard I/O streams, and then enter the kernel.
To end a sub-process, use _ exit (0) instead of exit (0 ). Because _ exit (0) does not perform any operation on the standard I/O Stream when the process ends, and exit (0) disables all standard I/O streams of the process.